I'm trying to create an ActionFilter that will read the Accept-Language header and find if it matches any value in locale and if it does not match, use the a default value which is "en".
First of all, this is my handler:
using MediatR;
using Microsoft.EntityFrameworkCore;
using Subscription.Domain.Common;
using Subscription.Domain.Exceptions;
using Subscription.Infrastructure.Configuration;
using System.Net;
namespace Subscription.API.Application.Package.Queries.Get
{
public class GetHandler : IRequestHandler<GetRequest, EntityResponseModel>
{
private readonly SubscriptionContext _context;
private readonly IHttpContextAccessor _httpContext;
public GetHandler(SubscriptionContext context, IHttpContextAccessor httpContext)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
_httpContext = httpContext;
}
public async Task<EntityResponseModel> Handle(GetRequest request, CancellationToken cancellationToken)
{
var lang = _httpContext.HttpContext.Request.Headers["Accept-Language"].ToString();
var packages = await _context.Packages.Where(x => !x.IsDeleted)
.Select(x => new GetResponseModel()
{
Id = x.Id,
BrandId = x.BrandId,
StartAt = x.StartAt,
IconUrl = x.IconUrl,
ImageUrl = x.ImageUrl,
CreatedAt = x.CreatedDate,
Title = x.PackageTranslations.FirstOrDefault(pt => pt.PackageId == x.Id && pt.Locale.Equals(lang)).Title,
Description = x.PackageTranslations.FirstOrDefault(pt => pt.PackageId == x.Id && pt.Locale.Equals(lang)).Description
}).ToListAsync();
if (!packages.Any())
{
throw new DomainException(HttpStatusCode.NotFound, "No record found.");
}
return new EntityResponseModel()
{
Data = packages
};
}
}
}
And this is the controller:
using Microsoft.AspNetCore.Mvc;
using MediatR;
using Subscription.API.Application.Package.Queries.Get;
using Subscription.API.Application.Bundle.Queries.GetById;
using Subscription.API.Filters;
namespace Subscription.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class PackagesController : ControllerBase
{
private readonly IMediator _mediator;
public PackagesController(IMediator mediator)
{
_mediator = mediator;
}
[HttpGet]
[ValidateHeaders]
public async Task<ActionResult> GetAll()
{
var response = await _mediator.Send(new GetRequest() { });
return Ok(response);
}
}
}
This the filter class:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace Subscription.API.Filters
{
public class ValidateHeaders : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var headers = context.HttpContext.Request.Headers;
// need to do something here
}
}
}
So, basically what I need is to create a filter that:
- Check the
Accept-Languageheader if it have a value that matches locale - If it does not have a value that matches it, return string with the default value which is
"en"
Any idea what I should do?
You can do this in 2 different ways;
1.Action Filter
If you use this action filter, you have to write this attribute on each endpoint.
2.Middleware
If you write it as middleware, it will be enough to place this middleware in the first place in the request pipeline.
This will effect all requests.
In the
Configuremethod inStartup.csor minimal api configuration inProgram.cs, use this middleware;