0

I have a web API controller, when I call the default Get action this works, when I call another specific action (GetReservationsForCustomer) this also works, but one action gives an error (GetReservationsByDate), it seems to route to the default Get action. Here is the code:

 // GET: api/Reservations public IQueryable<Reservation> GetReservations() { return db.Reservations; } [ResponseType(typeof(ReservationDTO))] public IHttpActionResult GetReservationsForCustomer(int CustomerId) { IEnumerable<Reservation> reservations = db.Reservations.Where(r => r.CustomerId == CustomerId).ToList(); List<ReservationDTO> reservationList = new List<ReservationDTO>(); foreach(Reservation reservation in reservations) { reservationList.Add(new ReservationDTO { id = reservation.id, ReservationStart = reservation.ReservationStart, Covers = reservation.Covers }); } return Ok(reservationList); } [ResponseType(typeof(ListReservationDTO))] public IHttpActionResult GetReservationsByDate(DateTime StartDate, DateTime EndDate) { IEnumerable<Reservation> reservations = new List<Reservation>(); if (EndDate != null) { reservations = db.Reservations.Where(r => r.ReservationStart.Date >= StartDate.Date && r.ReservationStart.Date >= EndDate.Date).ToList(); } else { reservations = db.Reservations.Where(r => r.ReservationStart.Date == StartDate.Date).ToList(); } List<ReservationDTO> reservationList = new List<ReservationDTO>(); foreach (Reservation res in reservations) { reservationList.Add(new ReservationDTO { id = res.id, ReservationStart = res.ReservationStart, Covers = res.Covers, CustomerEmail = res.Customer.EmailAddress, CustomerName = res.Customer.Name, CustomerPhone = res.Customer.PhoneNumber }); } return Ok(reservationList); } 

Here is my API call:

http://localhost:55601/api/Reservations/GetReservationsByDate/?StartDate=2018-03-04:T12:30:00

And here is the response:

{ "Message": "The request is invalid.", "MessageDetail": "The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Http.IHttpActionResult GetReservation(Int32)' in 'GreenLionBookings.API.ReservationsController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter." } 

Please note the specifics of the action are not relevant at this stage, I've butchered it a fair bit trying to get this to work! I've tried specifying a start date and end date and neither seems to work. It always seems to get routed to the default Get action.

Here is my RouteConfig:

public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } 

And here is my WebApiConfig:

 public static void Register(HttpConfiguration config) { // Web API configuration and services // Configure Web API to use only bearer token authentication. config.SuppressDefaultHostAuthentication(); config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); // Web API routes config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } 

So both basically just default.

Why is this not routing to the correct action, just for this one and not the others? I have another controller (Customers) which seems to work correctly for all actions too. I've read this and this, and also this and this which I actually thought was pretty relevant and quite helpful, but didn't solve my problem.

What am I doing wrong here?

10
  • endDate is a required parameter with no default. Therefore, that action is not a candidate for matching the route and the default route is chosen. That subsequently fails because there is no value for id. Commented Apr 8, 2018 at 6:24
  • 1
    You should leave out the action name of the url and let the framework match the request against the parameters name, try it like this localhost:55601/api/Reservations?StartDate=2018-03-04:T12:30:00 Commented Apr 8, 2018 at 6:37
  • 1
    looks like you have a typeo in the date, 2018-03-04:T12:30:00 should be 2018-03-04T12:30:00 Commented Apr 8, 2018 at 7:07
  • 1
    @MattG Np, should I post this as an answer then? Commented Apr 9, 2018 at 4:57
  • 1
    @MarcusHöglund yes please and I will mark as accepted. Cheers Commented Apr 11, 2018 at 5:56

1 Answer 1

1

First of all, you have a typeo in the date.

This 2018-03-04:T12:30:00 should be 2018-03-04T12:30:00.

Then, to solve the routing problem, you could leave out the action name of the url and let the framework match the request against the parameters name.

Try it like this

api/Reservations?StartDate=2018-03-04T12:30:00&EndDate=2018-03-05T12:30:00 

Then, if you want to be able to send nullable values to EndDate which is a value type of DateTime; make the DateTime nullable

[ResponseType(typeof(ListReservationDTO))] public IHttpActionResult GetReservationsByDate(DateTime StartDate, DateTime? EndDate) 

Notice the DateTime? which is a shorthand for Nullable<DateTime>

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.