Mediator Api call failing - asp.net-web-api

I'm trying to make a simple request using mediator and .net core. I'm getting an error that I am not understanding. All I'm trying to do is a simple call to get back a guid.
BaseController:
[Route("api/[controller]/[action]")]
[ApiController]
public class BaseController : Controller
{
private IMediator _mediator;
protected IMediator Mediator => _mediator ?? (_mediator = HttpContext.RequestServices.GetService<IMediator>());
}
Controller:
// GET: api/Customer/username/password
[HttpGet("{username}/{password}", Name = "Get")]
public async Task<ActionResult<CustomerViewModel>> Login(string username, string password)
{
return Ok(await Mediator.Send(new LoginCustomerQuery { Username = username,Password = password }));
}
Query:
public class LoginCustomerQuery : IRequest<CustomerViewModel>
{
public string Username { get; set; }
public string Password { get; set; }
}
View Model:
public class CustomerViewModel
{
public Guid ExternalId { get; set; }
}
Handler:
public async Task<CustomerViewModel> Handle(LoginCustomerQuery request, CancellationToken cancellationToken)
{
var entity = await _context.Customers
.Where(e =>
e.Username == request.Username
&& e.Password == Encypt.EncryptString(request.Password))
.FirstOrDefaultAsync(cancellationToken);
if (entity.Equals(null))
{
throw new NotFoundException(nameof(entity), request.Username);
}
return new CustomerViewModel
{
ExternalId = entity.ExternalId
};
}
This is the exception I am getting:
Please let me know what else you need to determine what could be the issue. Also, be kind I have been away from c# for a while.

Thanks for the info it was the missing DI. I added this
// Add MediatR
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>));
services.AddMediatR(typeof(LoginCustomerQueryHandler).GetTypeInfo().Assembly);
and we are good to go.

Related

System.AggregateException: Some services are not able to be constructed (Error while validating the service ..'ServiceType: MediatR.IRequestHandler

My CQRS file layout is as in the picture. Whenever I enable the handler inside the GetAllBooks folder, I get an error.
Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: MediatR.IRequestHandler2[BookAPI.Application.Features.Queries.Book.GetAllBooks.GetAllBookQueryRequest,System.Collections.Generic.List1[BookAPI.Application.Features.Queries.Book.GetAllBooks.GetAllBookQueryResponse]] Lifetime: Transient ImplementationType: BookAPI.Application.Features.Queries.Book.GetAllBooks.GetAllBookQueryHandler': Unable to resolve service for type 'BookAPI.Application.Repositories.IBookReadRepository' while attempting to activate 'BookAPI.Application.Features.Queries.Book.GetAllBooks.GetAllBookQueryHandler'.)
GetAllBookQueryHandler
public class GetAllBookQueryHandler : IRequestHandler<GetAllBookQueryRequest, List<GetAllBookQueryResponse>>
{
private IBookReadRepository bookReadRepository;
public GetAllBookQueryHandler(IBookReadRepository bookReadRepository)
{
this.bookReadRepository = bookReadRepository;
}
public async Task<List<GetAllBookQueryResponse>> Handle(GetAllBookQueryRequest request, CancellationToken cancellationToken)
{
List<B.Book> books = bookReadRepository.GetAll().Include(x=>x.Authors).Include(x=>x.Category).Include(x=>x.BookImages).ToList();
List<GetAllBookQueryResponse> responses = new();
foreach (B.Book book in books)
{
responses.Add(
new GetAllBookQueryResponse
{
Name= book.Name,
CategoryName=book.Category.Name,
AuthorName=book.Authors.First().Name,
Img=book.BookImages.First().Path,
UnitPrice=book.UnitPrice,
}
);
}
return responses;
}
}
GetAllBookQueryRequest
public class GetAllBookQueryRequest : IRequest<List<GetAllBookQueryResponse>>
{
//This place is empty as all books are requested
}
GetAllBookQueryResponse
public class GetAllBookQueryResponse
{
public int Id { get; set; }
public string Name { get; set; }
public string CategoryName { get; set; }
public string AuthorName { get; set; }
public string Img { get; set; }
public ushort UnitPrice { get; set; }
}
ServiceRegistration for IoC
using MediatR;
using Microsoft.Extensions.DependencyInjection;
namespace BookAPI.Application
{
public static class ServiceRegistration
{
public static void AddApplicationServices(this IServiceCollection services)
{
//find all handler, request and response and add IoC
services.AddMediatR(typeof(ServiceRegistration));
services.AddHttpClient();
}
}
}
Program.cs
I add services
builder.Services.AddApplicationServices();
Book Controller
.
.
.
readonly IMediator mediator;
public BookController(IBookWriteRepository bookWriteRepository, IWebHostEnvironment webHostEnvironment, IFileService fileService, IMediator mediator)
{
bookWriteRepository = bookWriteRepository;
_fileService = fileService;
this.mediator = mediator;
}
[HttpGet]
public async Task<IActionResult> GetAllBooks([FromQuery] GetAllBookQueryRequest getAllBookQueryRequest)
{
return Ok(await mediator.Send(getAllBookQueryRequest));
}
.
.
.
I guess it doesn't see the service I introduced, but I don't understand why GetAllBookHandler is throwing an error in the operation and not the others. For example, my handlers that list and create customers are working.

Blazor Session Storage

At my current project(blazor server side) I want to start using the session storage for user data like roles and names.
I've tried Blazored.SessionStorage and AspNetCore.Components.Server.ProtectedBrowserStorage.
The problem I'm facing is, that I just can't get the value(it's always null) and I don't know why.
Code I'm using:
public void GetUserInfo()
{
var x = sessionStorage.GetAsync<string>("Name");
var y = sessionStorage.GetAsync<string>("Email");
string Name = x.ToString();
string Email = y.ToString();
}
And
[Inject] public ProtectedSessionStorage sessionStorage { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
string Name = Helper.Name;
string Email = Helper.Email;
await sessionStorage.SetAsync("Name", Name);
await sessionStorage.SetAsync("Email", Email);
var x = sessionStorage.GetAsync<string>("Name");
var y = sessionStorage.GetAsync<string>("Email");
Name = x.Result.Value;
Email = y.Result.Value;
}
Thanks to everyone in advance and have a great day! :)
DO NOT USE THIS SOLUTION AS IS. WHEN I GET THE TIME I WILL UPDATE IT TO A WORKING SOLUTION
I suggest adding this as an injected object using Dependency Injection.
Create a class to hold this information and add is as a Scoped service.
Class:
public class UserInfo : IUserInfo //Create an interface
{
public static Name { get; set; }
public static Email { get; set; }
}
Injection (Program.cs on .NET 6):
public static async Task Main(string[] args)
{
//For WSAM
var builder = WebAssemblyHostBuilder.CreateDefault(args);
//For Server
var builder = WebApplication.CreateBuilder(args);
...
builder.Services.AddScoped<IUserInfo, UserInfo>(); //Scoped Service injection
}
Add data to injected service:
[Inject]
public IUserInfo UserInfo { get; set; }
protected override void OnInitialized() //Use whatever Life Cycle methods works for your implementation
{
UserInfo.Name = Helper.Name;
UserInfo.Email = Helper.Email;
}
Usage example:
#inject IUserInfo UserInfo
#page "/"
<div>#UserInfo.Name</div>
<div>#UserInfo.Email</div>

Parsing API response in Xamarin form

I am new to xamarin. I am trying to get data from php api but it doesn't give me any data or error kindly check. URL is
http://mehdibalti.000webhostapp.com/xamrin/getall.php
response is .. [{"Id":"1","Name":"Mehdi","Department":"Balti"},{"Id":"2","Name":"Mehdi","Department":"Syntecx"}]
and i did like this
public class EmployeeServices
{
public EmployeeServices()
{
}
public async Task<List<EmployeeModel>> getEmployeeAsyn(){
RestClient<EmployeeModel> resclient = new RestClient<EmployeeModel>();
var list =await resclient.GetTodoItemsAsync();
return list;
}
}
}
this is my resClient Class
public async Task<List<EmployeeModel>> GetTodoItemsAsync()
{
var httpClient = new HttpClient();
var response = await httpClient.GetStringAsync(getAllUrl);
response = response.Replace("\"", "");
var todoItems = JsonConvert.DeserializeObject<List<EmployeeModel>>(response);
return todoItems;
}
this is Model class
public class EmployeeModel
{
public string Id { get; set; }
public string Name { get; set; }
public string Department { get; set; }
}
but it did not return any list
The result API is giving you is not a list. Use stuff like http://json2csharp.com/
to investigate json you are getting.

Web API controller returning boolean

I have a Web API where one of the methods in a controller return true or false when validating user id which is a string of numbers. I do no have an actual database yet, so I sort of mocked up the set of values in the repository.
Below is my code:
My repository class:
public class myRepository
{
public myClasses.Employee[] GetAllEmployees()
{
return new myClasses.Employee[]
{
new myClasses.Employee
{
empId="111111",
empFName = "Jane",
empLName="Doe"
},
new myClasses.Employee
{
empId="222222",
empFName = "John",
empLName="Doe"
}
};
}
public bool VerifyEmployeeId(string id)
{
myClasses.Employee[] emp = new myClasses.Employee[]
{
new myClasses.Employee
{
empId="111111",
empFName = "Jane",
empLName="Doe"
},
new myClasses.Employee
{
empId="222222",
empFName = "John",
empLName="Doe"
}
};
for (var i = 0; i <= emp.Length - 1; i++)
{
if (emp[i].empId == id)
return true;
}
return false;
}
}
and my model class:
public class myClasses
{
public class Employee
{
public string empId { get; set; }
public string empFName { get; set; }
public string empLName { get; set; }
}
}
and here is my controller:
public class myClassesController : ApiController
{
private myRepository empRepository;
public myClassesController()
{
this.empRepository = new myRepository();
}
public myClasses.Employee[] GetEmployees()
{
return empRepository.GetAllEmployees();
}
public bool VerifyEmployee(string id)
{
return empRepository.VerifyEmployeeId(string id);
}
}
Now when i compile it I get an error:
} expected
Type or namespace definition, or end-of-file expected
; expected
in line
return empRepository.VerifyEmployeeId(string id);
of my controller.
My question is using boolean the best way to return Success or Failure from Web API method or is there a better way? and also why am I getting this error. I am new to Web API
The compile error is caused by this;
return empRepository.VerifyEmployeeId(string id);
You should rewrite to:
return empRepository.VerifyEmployeeId(id);
You don't have you specify the type of the argument when calling a function.
About returning true or false; if you intend to only check whether the employee is valid or not, I should leave it this way. If you plan to use that employee data more you could rewrite that function so it returns the actual employee itself, and return 404: Not Found when the Employee is not found for instance.

Confusion over MVC3 Code First / Repositories

Please can someone help me because I am getting confused.
I have an Entity like this:
public class Code
{
public int ID { get; set; }
public int UserID { get; set; }
public string CodeText { get; set; }
}
and an Interface like this:
public interface ICodeRepository
{
IQueryable<Code> Codes { get; }
void AddCode(Code code);
void RemoveCode(Code code);
Code GetCodeById(int id);
}
and a Repository like this:
public class SQLCodeRepository : ICodeRepository
{
private EFSQLContext context;
public SQLCodeRepository()
{
context = new EFSQLContext();
}
public IQueryable<Code> Codes
{
get { return context.Codes; }
}
public void AddCode(Code code)
{
context.Codes.Add(code);
context.SaveChanges();
}
public void RemoveCode(Code code)
{
context.Codes.Remove(code);
context.SaveChanges();
}
public Code GetCodeById(int id)
{
return context.Codes.Where(x => x.ID == id).FirstOrDefault();
}
}
and a Context like this:
public class EFSQLContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Code> Codes { get; set; }
public DbSet<PortfolioUser> PortfolioUsers { get; set; }
}
If I declare my controller like this:
public class SearchController : Controller
{
private ICodeRepository cRepo;
public SearchController(ICodeRepository codeRepository)
{
cRepo = codeRepository;
}
}
and then try to do cRepo.GetCodeById(1) nothing happens. But if I declare private ICodeRepository rep = new SQLCodeRepository and then call rep.GetCodeById(1) I can see the method in the Repository being called.
What am I doing wrong?
It looks like from the constructor signature, you are going to be doing some dependency injection. The step you are missing is to set up a DI container using a tool like Castle Windsor. You then configure the MVC resolver to use the DI container to give you the correct implementation of ICodeRepository.
See this
You'll need to create a resolver that implements IDependencyResolver and IDependencyScope and a controller factory that inheritsDefaultControllerFactory
Once you have those you can do something like the following:
MyContainer container; // this needs to be a class level member of the asax
var configuration = GlobalConfiguration.Configuration;
container = new MyContainer() // may need additional stuff here depending on DI tool used
configuration.DependencyResolver = new MyDependancyResolver(container);
var mvcControllerFactory = new MyFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(mvcControllerFactory);
You would call the above code from the asax Application_Start()
See this answer for more specifics on using Ninject and MVC3

Resources