Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web API 2 GET by query parameter

I'm going to switch from my WCF Rest/Json Service to WebApi2 and I'm looking for a way to map this method:

[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "Users?mail={mail}&pw={pw}")]
UserData getUserByEmailAndPw(String mail);

I want to query a user by email and password so I can't use the default GET which is intended to use an ID. As far as I know you should do this via attributes in Rest...

Do I just have to register a route for this or is there a better way (maybe by convention) ?

like image 522
stefan Avatar asked Aug 01 '15 08:08

stefan


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.

How do I use FromUri in Web API?

Using [FromUri] To force Web API to read a complex type from the URI, add the [FromUri] attribute to the parameter. The following example defines a GeoPoint type, along with a controller method that gets the GeoPoint from the URI.


1 Answers

You always have to register a route in WebApi for your controller actions, this can be done with attribute routing or with conventions based routing.

Parameters passed in the query string for GET request don't really have to be specified explicitly in either of the routing configuration methods.

The parameters you specify on your controller action get mapped to parameters sent in the query string of a GET request.

If you are using the default WebApi conventions based setup where the routes are configured something like this:

var config = new HttpConfiguration();
// some other config setup for web api
...
...
// route config
config.Routes.MapHttpRoute(
    name: "API Default",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

Then a controller like this will work for you:

public class UsersController : ApiController {
   // this maps to a get requests to:
   // domain/api/users
   // and domain/api/users?id=someid
   // and domain/api/users?mail=somemail
   // and domain/api/users?pw=somepw
   // and domain/api/users?mail=somemail&pw=somepw
   // and domain/api/users with any query string really
   [HttpGet]
   public IHttpActionResult Get(string mail, string pw) {
      // should probably check mail and pw for empty strings and nulls
      var users = SomeStaticExampleService.FindByMailAndPw(mail, pw);
      return this.Json(users);
   }
}

Alternatively you can use attribute routing and then call your controllers and action methods whatever you want. Configure your routes like this:

var config = new HttpConfiguration();
// some other config setup for web api
...
...
// route config
config.MapHttpAttributeRoutes();

Then you can create a controller like this:

public class FooController : ApiController {
   // this maps to a get requests to:
   // domain/users
   // and domain/users?id=someid
   // and domain/users?mail=somemail
   // and domain/users?pw=somepw
   // and domain/users with any query string really
   [HttpGet]
   [Route("users")]
   public IHttpActionResult Bar(string mail, string pw) {
      // should probably check mail and pw for empty strings and nulls
      var users = SomeStaticExampleService.FindByMailAndPw(mail, pw);
      return this.Json(users);
   }
}

Bear in mind though that with Attribute Routing you have to be careful not to create clashing routes otherwise WebApi won't know which controller and action to route a request to when a route is mapped to multiple action methods.

I've used this.Json in these examples to return a http response with json content to match your wcf ResponseFormat = WebMessageFormat.Json. But you can of course just return a CLR type:

   [HttpGet]
   [Route("users")]
   public IEnumerable<MyUser> Bar(string mail, string pw) {
      // should probably check mail and pw for empty strings and nulls
      var users = SomeStaticExampleService.FindByMailAndPw(mail, pw);
      return users;
   }

and let WebApi's content negotiation handle the response message content type.

like image 164
Anish Patel Avatar answered Oct 07 '22 02:10

Anish Patel