简体   繁体   中英

Web API validator that can access the route parameters/controller context

I have a Web API model of the lines

class SampleModel
{
    [ComponentExistsValidation]
    public Guid? ComponentID { get; set; }
    ...
}

I need to validate that the ComponentID exists under a given model, and the modelid is available to my controller as a route parameter.

[Route("api/model/addcomponents/{modelid:int}")]
public async Task AddComponents(int modelid, [FromBody]SampleModel[] components)

Here is my validator

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
    if (value == null)
        return ValidationResult.Success;
    Guid componentid = (Guid)value;
    int modelid; // How do I get this here?
    Model context_mdl = Model.GetModel(modelid);
    if(!context_mdl.HasComponent(componentid))
    {
        return new ValidationResult(string.Format("Invalid component"));
    }
}

Can I access the modelid route parameter in the validator?

You should be able to get it from HttpContext .

Add a reference to System.Web.DLL if HTTPContext is unavailable.

Here's an example using IValidatableObject . But I'm sure you can translate it to your attribute if you want.

class SampleModel : IValidatableObject
{
    public Guid? ComponentID { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (value == null)
            return ValidationResult.Success;
        Guid componentid = (Guid)value;
        int modelid = System.Web.HttpContext.Current.Request.RequestContext.RouteData.GetWebApiRouteData("modelid");
        Model context_mdl = Model.GetModel(modelid);
        if(!context_mdl.HasComponent(componentid))
        {
            yield return new ValidationResult(string.Format("Invalid component"));
        }
    }
}

And use an extension heavily influensed from this answer .

public static class WebApiExtensions
{
    public static object GetWebApiRouteData(this RouteData routeData, string key)
    {
        if (!routeData.Values.ContainsKey("MS_SubRoutes"))
            return null;

        object result = ((IHttpRouteData[]) routeData.Values["MS_SubRoutes"]).SelectMany(x => x.Values)
            .Where(x => x.Key == key).Select(x => x.Value).FirstOrDefault();
        return result;
    }
}

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