mr_coder
mr_coder

Reputation: 69

.NET Core Mediatr Usage not all code paths return a value

In my API, I am trying to use MediatR; so in my controller code, I wrote:

[HttpPost("AdminLogin")    
public async Task<ActionResult<Admin>> GetContractById(Admin admin)
{
    var response = await _mediator.Send(new UserLoginRequest(admin));    

    if (response.HasError)
    {
        return BadRequest(response);
    }    

    return Ok(response);
}

Then in my UserLoginRequest.cs I wrote this code:

using MediatR;
using SinavAlemiPanel.Domain.Models;
using SinavAlemiPanel.Infrastructure.Interfaces;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SinavAlemiPanel.Application.Requests.UserRequests
{
    public class UserLoginRequest :IRequest<BaseResponse<Admin>>
    {
        private Admin admin;

        public UserLoginRequest(Admin admin)
        {
            this.admin = admin;
        }

        public Admin UserCredentials { get; set; }
    }

    public sealed class UserLoginRequestHandlers : IRequestHandler<UserLoginRequest, BaseResponse<Admin>>
    {
        private readonly IUserService _userService;

        public UserLoginRequestHandlers(IUserService userService)
        {
            _userService = userService;
        }

        public async Task<BaseResponse<Admin>> Handle(UserLoginRequest request, CancellationToken cancellationToken)
        {
            await Task.Run(() =>
            {
                return _userService.Login(request.UserCredentials);
            });
        }
    }
}

And in my service I have:

using Dapper;
using SinavAlemiPanel.Domain.Models;
using SinavAlemiPanel.Infrastructure.Interfaces;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

namespace SinavAlemiPanel.Infrastructure.Services
{
    public class UserService : IUserService
    {
        private readonly IBaseService _baseService;
        private readonly DBConnection _db;

        public UserService(IBaseService baseService)
        {
            _baseService = baseService;
        }

        public Admin Login(Admin admin)
        {   
            Admin result = new Admin();
            var dynamicParams = new DynamicParameters();
            var conn = _baseService.GetConnection(_db.GetConnString());

            try
            {
                dynamicParams.Add("@username", admin.Username, DbType.String, ParameterDirection.Input);
                dynamicParams.Add("@pass", admin.Password, DbType.String, ParameterDirection.Input);

                result = SqlMapper.Query<Admin>(conn, "dbo.SP_Admin_Login @username, @pass", dynamicParams).SingleOrDefault();

                conn.Close();

                if (result != null && result.Id > 0)
                {
                    result.Accesses = (result != null && result.Id > 0) ? Accesses(result.Id) : new List<Access>();
                }

                return result;
            }
            catch(Exception ex)
            {
                return result;
            }
        }

        public List<Access> Accesses(int refAdmin)
        {
            List<Access> result = new List<Access>();
            var dynamicParams = new DynamicParameters();

            var conn = _baseService.GetConnection(_db.GetConnString());

            try
            {
                dynamicParams.Add("@refAdmin", refAdmin, DbType.Int32, ParameterDirection.Input);

                result = SqlMapper.Query<Access>(conn, "dbo.SP_Admin_Accesses @refAdmin", dynamicParams).ToList();

                conn.Close();

                return result;
            }
            catch (Exception e)
            {
                return result;
            }
        }
    }
}

My problem is that the code doesn't accept in request handle, I get this error:

Error CS0161
'UserLoginRequestHandlers.Handle(UserLoginRequest, CancellationToken)': not all code paths return a value

I am new in C# so I couldn't detect the error. How can I solve this issue?

Thanks in advance

Upvotes: 0

Views: 475

Answers (2)

Anderson Bernardo
Anderson Bernardo

Reputation: 21

The another approach is to create your service as async:

 public async Task<Admin> Login(Admin admin)

And you need a corresponding constructor in your BaseResponse class:

public async Task<BaseResponse<Admin>> Handle(UserLoginRequest request, CancellationToken cancellationToken)
{   
    Admin admin = await _userService.Login(request.UserCredentials);           
   
    return new BaseResponse<Admin>(admin);            
}

BaseResponse example:

public class BaseResponse<T>
{
    private T Response;

    public BaseResponse(T response)
    {
        Response = response;
    }
}

Upvotes: 2

Guru Stron
Guru Stron

Reputation: 141635

You are missing a return statement in the Handle method, but adding it alone won't fix the compilation you need to translate Admin returned by _userService.Login to BaseResponse<Admin>. Also since _userService.Login is a sync method - no need for Task.Run and assync-await - use Task.FromResult instead. Something like this (assiming the existence of corresponding BaseResponse ctor):

public Task<BaseResponse<Admin>> Handle(UserLoginRequest request, CancellationToken cancellationToken)
{
    var admin = _userService.Login(request.UserCredentials);
    return Task.FromResult(new BaseResponse<Admin>(admin)); // no need for Task.Run and async-await cause Login is synchronous method
}

Upvotes: 3

Related Questions