Fluttterda signalR bağlantım çalışmıyor .net core ile bir backend servis yazdım ve signalr da grupları kulanmam gerekiyor

using Azure.Core;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using MotorSocialApp.Api.Hubs;
using MotorSocialApp.Application.Features.Group.Command.CreateGroup;
using MotorSocialApp.Application.Features.Group.Command.JoinGroup;
using MotorSocialApp.Application.Features.Group.Command.SendMessageGroup;
using MotorSocialApp.Application.Features.Group.Queries.GetAllChatGroups;
using MotorSocialApp.Application.Features.Group.Queries.GetGroupMessagesByGroupId;
using MotorSocialApp.Application.Features.Group.Queries.GetUserChatGroups;
using MotorSocialApp.Application.Features.Post.Command.CreatePost;
using MotorSocialApp.Application.Features.Post.Queries.GetAllPost;
using MotorSocialApp.Domain.Entities;
using System.Text.RegularExpressions;

namespace MotorSocialApp.Api.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class ChatGroupController : ControllerBase
    {

        private readonly IMediator _mediator;
        private readonly IHubContext<ChatGroupHubService> _hubContext;
  

        public ChatGroupController(IMediator mediator, IHubContext<ChatGroupHubService> hubContext)
        {
            _mediator = mediator;
            this._hubContext = hubContext;
           
        }

        [Authorize]
        [HttpPost]
        public async Task<IActionResult> CreateChatGroup(CreateGroupCommandRequest request)
        {

            try
            {
                await _mediator.Send(request);

                // SignalR üzerinden istemcilere bildir
                await _hubContext.Clients.All.SendAsync("ChatGroup", new
                {

                    Name = request.Name,
                    GroupIconPath = request.GroupIconPath,
                    GroupAdminUserId = request.GroupAdminUserId,
                    GroupDescription = request.GroupDescription,
                });


                return Ok();
            }
            catch (Exception ex) { return BadRequest(ex.Message); }

        }

        [Authorize]
        [HttpPost]
        public async Task<IActionResult> JoinGroup(JoinGroupCommandRequest request)
        {

            try
            {
                await _mediator.Send(request);
                return Ok();
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }

        }

        //[Authorize]
        //[HttpPost]
        //public async Task<IActionResult> CreateJoinGroupConnection(JoinGroupCommandRequest request)
        //{

        //    try
        //    {
               
        //        return Ok();
        //    }
        //    catch (Exception ex)
        //    {
        //        return BadRequest(ex.Message);
        //    }

        //}




        [Authorize]
        [HttpPost]
        public async Task<IActionResult> SendMessageGroup(SendMessageGroupRequest request)
        {

            try
            {
                await _mediator.Send(request);
                // SignalR üzerinden istemcilere bildir
                await _hubContext.Clients.Groups(request.GroupId.ToString()).SendAsync("GroupChatMessage", new
                {
                    GroupId = request.GroupId,
                    SenderUserId = request.SenderUserId,
                    SenderUserName = request.SenderUserName,
                    Content = request.Content,
                    SentAt = request.SentAt,
                });
                return Ok();
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }

        }

        [Authorize]
        [HttpGet]
        public async Task<IActionResult> GetAllChatGroups()
        {

            try
            {
                var result = await _mediator.Send(new GetAllChatGroupsQueryRequest());
                return Ok(result);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }

        }

        //[Authorize]
        [HttpGet]
        public async Task<IActionResult> GetUserChatGroups(Guid userId)
        {

            try
            {
                var result = await _mediator.Send(new GetUserChatGroupsQueryRequest
                {
                    UserId = userId
                });
                return Ok(result);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }

        }
        //[Authorize]
        [HttpGet]
        public async Task<IActionResult> GetGroupMessagesByGroupId(Guid groupId)
        {

            try
            {
                //await _service.JoinGroup(groupId.ToString());
                var result = await _mediator.Send(new GetGroupMessagesByGroupIdQueryRequest
                {
                    GroupId = groupId
                });
                return Ok(result);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }

        }
    }
}

using Serilog;
using MotorSocialApp.Persistence;
using MotorSocialApp.Application;
using MotorSocialApp.Infrastructure;
using MotorSocialApp.Application.Exceptions;
using Microsoft.OpenApi.Models;
using Microsoft.AspNetCore.SignalR;
using MotorSocialApp.Api.Hubs; // SignalR için gerekli

var builder = WebApplication.CreateBuilder(args);

// Serilog yapılandırmasını ekleyin
Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(builder.Configuration)
    .CreateLogger();

// Serilog'u ASP.NET Core'a ekleyin
builder.Host.UseSerilog();

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddHttpContextAccessor();
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();



var env = builder.Environment;

builder.Configuration.SetBasePath(env.ContentRootPath)
    .AddJsonFile("appsettings.json", optional: false)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

builder.Services.AddPersistence(builder.Configuration);
builder.Services.AddInfrastructure(builder.Configuration);
builder.Services.AddApplication();

// SignalR Servisini Ekleyin
builder.Services.AddSignalR(options =>
{
    // Keep-alive interval: Sunucu, istemciyle bağlantının hala aktif olduğunu göstermek için ping gönderir.
    options.KeepAliveInterval = TimeSpan.FromSeconds(15); // Varsayılan: 15 saniye

    // Client timeout: İstemci sunucudan ping almazsa bu süre sonunda bağlantının kesildiğini düşünür.
    options.ClientTimeoutInterval = TimeSpan.FromSeconds(30); // Varsayılan: 30 saniye

    
});

builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "MotorSocialApp", Version = "v1", Description = "MotorSocialApp API swagger client." });
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
    {
        Name = "Authorization",
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer",
        BearerFormat = "JWT",
        In = ParameterLocation.Header,
        Description = "'Bearer' yazip bosluk biraktiktan sonra Token'i girebilirsiniz \r\n\r\n Örnegin: \"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\""
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement()
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                }
            },
            Array.Empty<string>()
        }
    });
});

builder.Services.AddAuthorization();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.ConfigureExceptionHandlingMiddleware();

app.UseStaticFiles();
app.UseRouting();

// CORS Middleware'i buraya ekleyin
app.UseCors("AllowFlutterLocalhost");

app.UseAuthentication(); // Authentication önce
app.UseAuthorization();   // Authorization sonra

// SignalR için Hub Endpoint'i Ekleyin
app.MapHub<ExploreHubService>("/exploreHub");
app.MapHub<ChatGroupHubService>("/chatGroupHub");

app.MapControllers();

app.Run();

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using MotorSocialApp.Domain.Entities;

namespace MotorSocialApp.Api.Hubs
{

    public class ChatGroupHubService : Hub

    {
        // Kullanıcıyı belirli bir gruba katmak
        public async Task JoinGroup(string groupId)
        {
            await Groups.AddToGroupAsync(Context.ConnectionId, groupId);
        }

        // Kullanıcıyı bir gruptan çıkarmak
        public async Task LeaveGroup(string groupId)
        {
            await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupId);
        }


        public async Task NewChatGroupMessage(GroupChatMessage message)
        {

            await Clients.Groups(message.GroupId.ToString()).SendAsync("GroupChatMessage", message);
        }

        public async Task NewChatGroupMessage1(GroupChatMessage message)
        {

            await Clients.All.SendAsync("GroupChatMessage1", message);
        }

        // Yeni bir post eklendiğinde tüm istemcilere bildir.
        public async Task NewChatGroup(ChatGroup chatGroup)
        {
            await Clients.All.SendAsync("ChatGroup", chatGroup);
        }


    }
}

bunlar benim .net core tarafındaki kodlarım. Burada yapmak istediğim şey aşağıdaki fonksiyonun çalıştırılması

        // Kullanıcıyı belirli bir gruba katmak
        public async Task JoinGroup(string groupId)
        {
            await Groups.AddToGroupAsync(Context.ConnectionId, groupId);
        }
import 'package:flutter/cupertino.dart';
import 'package:moto_kent/constants/api_constants.dart';
import 'package:moto_kent/models/chat_group_message_model.dart';
import 'package:signalr_netcore/signalr_client.dart';

class SignalRMessageService {
  late HubConnection _connection;
  final VoidCallback? onMessageReceived;
  final VoidCallback? onGroupJoined;
  final VoidCallback? onGroupLeft;


  SignalRMessageService({
    this.onMessageReceived,
    this.onGroupJoined,
    this.onGroupLeft,
  });

  VoidCallback? onReceivePost;

  Future<void> initializeSignalR() async {
    // Hub bağlantısını başlat
    _connection = HubConnectionBuilder()
        .withUrl(ApiConstants.signalRChatGroupEndpoint,

    )

        .build();

    // Bağlantı kapandığında çağrılacak geri çağırım
    _connection.onclose(({Exception? error}) {
      if (error != null) {
        print("SignalR bağlantısı kapandı: ${error.toString()}");
      } else {
        print("SignalR bağlantısı kapandı.");
      }
    });

    // Grup mesajlarını dinle
    _connection.on("GroupChatMessage1", (arguments) async {
      if (arguments != null && arguments.isNotEmpty) {
        try {
          final json = arguments[0] as Map<String, dynamic>;
          ChatGroupMessageModel message = ChatGroupMessageModel.fromJson(json);
          // Callback ile gelen mesajı işle
          onMessageReceived?.call();
          print("Yeni mesaj alındı: ${message.content}");
        } catch (e) {
          print("Mesaj işlenirken hata: $e");
        }
      }
    });

    // Bir kullanıcı gruba katıldığında çağrılır
    _connection.on("JoinGroup", (arguments) {
      print("Bir kullanıcı gruba katıldı: $arguments");
      onGroupJoined?.call();
    });

    // Bir kullanıcı gruptan ayrıldığında çağrılır
    _connection.on("LeaveGroup", (arguments) {
      print("Bir kullanıcı gruptan ayrıldı: $arguments");
      onGroupLeft?.call();
    });

    try {
      await _connection.start();
      print("SignalR bağlantısı başarılı.");
    } catch (e) {
      print("SignalR bağlantı hatası: $e");
    }
  }

  /// Kullanıcıyı bir gruba kat
  Future<void> joinGroup(String groupId) async {
    if (_connection.state == HubConnectionState.Connected) {
      await _connection
          .invoke("JoinGroup", args: ["groupId"]);
      try {
        print("Gruba katılma işlemi başarılı: $groupId");
      } catch (e) {
        print("Gruba katılma hatası: $e");
      }
    } else {
      print("SignalR bağlantısı aktif değil.");
    }
  }

  /// Kullanıcıyı bir gruptan çıkar
  Future<void> leaveGroup(String groupId) async {
    if (_connection.state == HubConnectionState.Connected) {
      try {
        await _connection.invoke("LeaveGroup", args: [groupId]);
        print("Gruptan ayrılma işlemi başarılı: $groupId");
      } catch (e) {
        print("Gruptan ayrılma hatası: $e");
      }
    } else {
      print("SignalR bağlantısı aktif değil.");
    }
  }

  /// Gruba yeni bir mesaj gönder
  Future<void> sendMessageToGroup(ChatGroupMessageModel message) async {
    if (_connection.state == HubConnectionState.Connected) {
      try {
        await _connection.invoke("NewChatGroupMessage1", args: [message.toJson()]);
        print("Mesaj gruba gönderildi: ${message.content}");
      } catch (e) {
        print("Mesaj gönderme hatası: $e");
      }
    } else {
      print("SignalR bağlantısı aktif değil.");
    }
  }

  /// Tüm istemcilere yeni bir grup bildirimi gönder
  Future<void> notifyNewChatGroup(dynamic chatGroup) async {
    if (_connection.state == HubConnectionState.Connected) {
      try {
        await _connection.invoke("NewChatGroupMessage1", args: [chatGroup]);
        print("Yeni grup bildirimi gönderildi.");
      } catch (e) {
        print("Grup bildirimi gönderme hatası: $e");
      }
    } else {
      print("SignalR bağlantısı aktif değil.");
    }
  }

  /// Bağlantıyı durdur
  void dispose() {
    _connection.stop();
  }
}

flutter tarafında ise signalR için yazdığım servis bu. View sayfamda bu kodları şu şekilde çalıştırıyorum

 @override
  void initState() {
    super.initState();

    var viewmodel = context.read<SendMessageViewmodel>();

    // Sayfa açıldığında listeyi en sona kaydır
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _scrollToBottom();
      context.read<SendMessageViewmodel>().fetchMessageList(widget.groupId!);
      messageService = SignalRMessageService(
        onGroupJoined: () {
          print("gruba katıldınız");
        },
      );

      messageService.onReceivePost = () {
        setState(() {
          // Kaydırma işlemini bir sonraki frame'e planlayarak gerçekleştir
          WidgetsBinding.instance.addPostFrameCallback((_) {
            _scrollToBottom();
          });
        });
      };

      messageService.initializeSignalR().then((value) {
        messageService.joinGroup(widget.groupId!);

      },);

    });
  }

signalR bağlantısı başarılı bir şekilde gerçekleşiyor yani flutter tarafında yazdığım signalR servisini bu kısmı düzgün çalışıyor

try {
      await _connection.start();
      print("SignalR bağlantısı başarılı."); //>> bu çıktıyı alıyorum
    } catch (e) {
      print("SignalR bağlantı hatası: $e");
    }

fakat

  /// Kullanıcıyı bir gruba kat
  Future<void> joinGroup(String groupId) async {
    if (_connection.state == HubConnectionState.Connected) {
      await _connection
          .invoke("JoinGroup", args: ["groupId"]);
      try {
        print("Gruba katılma işlemi başarılı: $groupId");
      } catch (e) {
        print("Gruba katılma hatası: $e");
      }
    } else {
      print("SignalR bağlantısı aktif değil.");
    }
  }

fonksiyonum çalışmaya başladığında

E/flutter ( 6674): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Server returned an error on close: Connection closed with an error.

bu hatayı alıyorum . Bu sorunu bir türlü çözemedim . Gruplara ayırmadığımda ve controllerde

       [Authorize]
       [HttpPost]
       public async Task<IActionResult> SendMessageGroup(SendMessageGroupRequest request)
       {

           try
           {
               await _mediator.Send(request);
               // SignalR üzerinden istemcilere bildir
               await _hubContext.Clients.Groups(request.GroupId.ToString()).SendAsync("GroupChatMessage", new
               {
                   GroupId = request.GroupId,
                   SenderUserId = request.SenderUserId,
                   SenderUserName = request.SenderUserName,
                   Content = request.Content,
                   SentAt = request.SentAt,
               });
               return Ok();
           }
           catch (Exception ex)
           {
               return BadRequest(ex.Message);
           }

bu kod yerine


        [Authorize]
        [HttpPost]
        public async Task<IActionResult> SendMessageGroup(SendMessageGroupRequest request)
        {

            try
            {
                await _mediator.Send(request);
                // SignalR üzerinden istemcilere bildir
                await _hubContext.Clients.All.SendAsync("GroupChatMessage", new
                {
                    GroupId = request.GroupId,
                    SenderUserId = request.SenderUserId,
                    SenderUserName = request.SenderUserName,
                    Content = request.Content,
                    SentAt = request.SentAt,
                });
                return Ok();
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }

        }

bunu kullanıp tüm istemcilere mesaj gönderebiliyorum . Yukarıda bahsettiğim sorunu nasıl çözebilirim daha önce buna benzer bir hata aldınız mı ?

Foruma hoş geldin genç kardeşim. Kodlarını forumdaki editör düzgün biçimlendirmemiş şu anda. Pek anlaşılmıyor, uygun olan konu uzmanı arkadaşlar yardımcı olacaktır.

1 Beğeni

Merhabalar,

Projeniz calistirilamiyor. Gereksinimlerin bir kismini tahmin ettikten sonra bile MotorSocialApp’ten eksikleri var. Kodu sadece okumak durumundayiz.

Bu hata nedir?
Baglantiyi bir hatayla kapatmis, o hatanin ne oldugunu bulmaniz lazim.
Server tarafinda da bir yerlere yaziyor olabilir. Yazmiyorsa yakalayip yazdirmaniz lazim. Bir yerlerde Exception throw ediliyor olmasi muhtemel.

SignalR ile daha once (2018 civari olmasi lazim) calismis biri olarak, akliniza gelmeyecek abuk subuk seylere hazirlikli olmanizi oneririm. Ben calisirken .NET ve .NET core verisyonlari farkliydi mesela. Bir tanesi bir yonde deger dondurulmesine izin vermiyordu. “Su mesaji soyle handle et” diyebilmektense assembly icinde reflection ile aranan, tam istenilen ozelliklere sahip sinif/fonksiyonlari bulup uygunsuz vakitlerde cagiriyordu. Mesaj uzerine cagrilan metodlarin this’leri birbirini tutmuyordu (her mesaj icin yeni instance yaratiyordu yanlis hatirlamiyorsam); baglanti baglami tutabilmek icin disarilardan sihirli seyler cagrilmasi gerekiyordu. Cogu Microsoft teknolojisi gibi, eger tam olarak tasarlayan insanlarin kullandigi (ve dokumente edilmemis) sekilde kullanmiyorsaniz, surprizlerle dolu. Bir nevi mayin tarlasi.

Yakaladiginiz exception’lari BadRequest’e cevirmeden once loglamaniz lazim. Serilog kullaniyorsunuz; ona yollayabilirsiniz.

1 Beğeni