yavg
yavg

Reputation: 3061

Middleware using the parameters that is sent from the client side and allow or not the interaction with the endpoint depending on these parameters

I am using c# core 3.1 I have several endpoints with a structure similar to this:

[HttpPost]
public async Task<ActionResult<Usuario>> Post([FromBody] User user) 
{
        context.User.Add(user);
        try
        {
             await context.SaveChangesAsync();
        }
        catch (Exception ex)
        {
           ...
        }
         return Ok();
}

The user sends an object like this:

{"rol": "Administrator", "name":"pedro"}

I would like to validate that if it contains a certain value, allow to continue with the endpoint logic or otherwise do not allow it. for example I want to make a verification that if rol= Administrator allows to continue with my endpoint.

I am very confused but I don't know if something like this exists but it works as a middleware where can I get the data that is sent from the client side to perform validations:

[HttpPost]
[MyCustomMiddleWare]
.
.

public class MyCustomMiddleWare
{
 .
 .
 if (dataFromClientSide.rol== "Administrator")
 {
     continue
 }
 else{
   return Ok(new { message:"Not has permission" })
 } 
}

Upvotes: 3

Views: 137

Answers (1)

spzvtbg
spzvtbg

Reputation: 1034

It looks like you just need some modelvalidation like bellow:

using Microsoft.AspNetCore.Mvc;

using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;

[ApiController]
[Route("api/[controller]")]
public class YourController : ControllerBase
{
    public class User
    {
        [RegularExpression(pattern: "Administrator", ErrorMessage = "Your error message.")]
        public string Role { get; set; }

        public string Name { get; set; }
    }

    [HttpPost]
    public async Task<IActionResult> PostAsync([FromBody] User user)
    {
        if (this.ModelState.IsValid)
        {
            return this.ValidationProblem();
        }

        // Do something here;

        return this.Ok();
    }
}

Thats the result from invalid role.

But if you insist to do it with middleware it will looks like this bellow:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseMiddleware<UserRoleMiddleware>();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

    public class UserRoleMiddleware
    {
        private readonly RequestDelegate next;

        public UserRoleMiddleware(RequestDelegate next)
        {
            this.next = next;
        }

        public async Task Invoke(HttpContext httpContext)
        {
            using var reader = new StreamReader(httpContext.Request.Body);

            var body = await reader.ReadToEndAsync();
            var user = JsonConvert.DeserializeObject<User>(body);

            if (user != null && !user.Role.Equals("Administrator", StringComparison.OrdinalIgnoreCase))
            {
                // Redirect or do somethings else.
            }

            await next(httpContext);
        }
    }

To validate specific endpoints just implement ActionFilterAttribute:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<AdministratorAttribute>();
    }

    public class AdministratorAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            if (context.ActionArguments.TryGetValue("user", out object user))
            {
                if (!(user as User).Role.Equals("Administrator"))
                {
                    // Redirect or something
                }
            }

            base.OnActionExecuting(context);
        }
    }

    [HttpPost]
    [Administrator]
    public async Task<IActionResult> PostAsync([FromBody] User user)
    {
        return this.Ok();
    }

Upvotes: 3

Related Questions