简体   繁体   中英

How to know if a model or ActionExecutingContext argument is an entity (asp.net core 5)

I'm starting a new project targeted .net 5 using ASP.NET Core 5 .

Sometimes in some Actions in some Controllers I need to check the received model if it is valid or not, so I created an ActionFilter class to use with any Action I want, all these actions will be HttpPost and will receive a model . The problem is I tired from thinking about the best solution to know if the model is an entity or not from OnActionExecuting method, so I decided to make all my entities inherited from an interface named IEntity and in OnActionExecuting method check if a parameter is inherited from IEntity and check it's value as shown below.

What I try:

public class ValidationFilterAttribute : IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext context)
        {
            var param = context.ActionArguments.SingleOrDefault(p => p.Value is IEntity);
            if(param.Value == null)
            {
                context.Result = new BadRequestObjectResult("Object is null");
                return;
            }
            
            if(!context.ModelState.IsValid)
            {
                context.Result = new BadRequestObjectResult(context.ModelState);
            }
        }
        public void OnActionExecuted(ActionExecutedContext context)
        {          
        }
    }

Question:

Please is there any good method or technique to know if the model or one of the context parameters is an Entity without using Interface?

Defining a marker interface for your entity types is not a bad idea. But it's not always applicable depending on your design. With the entity type itself, you cannot tell the difference from the normal types. But with the help of the DbContext containing the entity types, you can check if a type is an entity type by using the method IModel.FindEntityType

public class ValidationFilterAttribute : IActionFilter
{
    readonly YourDbContext _dbContext;
    public ValidationFilterAttribute(YourDbContext dbContext){
         _dbContext = dbContext;
    }
    public void OnActionExecuting(ActionExecutingContext context)
    {
        var hasAtLeastOneEntity = context.ActionArguments
                                         .Any(e => e.Value != null && 
                                                   _dbContext.Model.FindEntityType(e.Value.GetType()) != null);
        if(!hasAtLeastOneEntity)
        {
            context.Result = new BadRequestObjectResult("Object is null");
            return;
        }
        
        if(!context.ModelState.IsValid)
        {
            context.Result = new BadRequestObjectResult(context.ModelState);
        }
    }
    public void OnActionExecuted(ActionExecutedContext context)
    {          
    }
}

As in the code above, I assume that your DbContext type is YourDbContext , you can replace it with your actual DbContext type.

The performance should be good enough but in case you want it super fast (after performing some benchmarking and find it a bit slow), you can apply some caching strategy on the entity types. Although I'm not so sure if the default implementation of IModel itself should use some internal cache to manage the entity types.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM