Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asp.net Web API normalize arguments

Say I have a controller like:

public class MyController : ApiController {
    [Route("{myarg}")]
    [HttpGet]
    public async Task<Foo> Get(string myarg)
    {
        return await ...
    }
}

The myarg argument needs to be 'normalized'. Let's say I always want to trim it, uppercase it and string-reverse it. The actual operations don't matter, they're just an example so I'm not looking for methods to trim or reverse a string.

I have a bunch of controllers with all a bunch of methods with all similar arguments. I'd like to have a way to annotate those methods or do something else to make sure the arguments are always 'normalized' before they are even passed into the method. I have looked into route constraints (custom route constraints in particular) but that doesn't provide a method to do what I want (which makes sense since it's not a real constraint).

Ideally I'd like to annotate the method with an attribute like:

[MyNormalize("{myarg}")]

Or something in a similar fashion like the RouteAttributes. What would be the best way to go about this and implement this in a clean fashion?

like image 510
RobIII Avatar asked Aug 23 '18 12:08

RobIII


People also ask

What is difference between FromQuery and FromBody?

[FromQuery] - Gets values from the query string. [FromRoute] - Gets values from route data. [FromForm] - Gets values from posted form fields. [FromBody] - Gets values from the request body.

What is FromBody and FromUri in Web API?

The [FromUri] attribute is prefixed to the parameter to specify that the value should be read from the URI of the request, and the [FromBody] attribute is used to specify that the value should be read from the body of the request.

Can we use FromBody with Httpget?

A Get does not send the body of the form, it only requests a URL. Use a <form> in your view and post it to your controller method, which needs to be decorated with HttpPost.


1 Answers

It's worth noting that ideally, you'll only want to tweak model-binding in order to correctly bind the passed value, not transforming it.

Anyway, here's the custom model-binder:

public class MyArgModelBinder : System.Web.Http.ModelBinding.IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, System.Web.Http.ModelBinding.ModelBindingContext bindingContext)
    {
        var val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        // transform to upper-case
        var transformedValue = val.AttemptedValue.ToUpperInvariant();

        bindingContext.Model = transformedValue;

        return true;
    }
}

Then apply it:

[Route("{myarg}")]
[HttpGet]
public async Task<Foo> Get([ModelBinder(typeof(MyArgModelBinder))] string myarg)
{
    // at this point, `myarg` would contain the transformed value

    ...
}

See Documentation

like image 113
haim770 Avatar answered Sep 19 '22 00:09

haim770