0

I have no idea where to start with this. I asked a question previously, and someone suggested I look at attribute routing. I read up on it, and while it helped me to create the below code, I'm still not sure how to limit it like I want to.

public class ReviewController : ApiController { private Review db = new Review(); ////This GET works. It was auto-generated by Visual Studio. // GET: api/Review public IQueryable<Review> GetReview() { return db.Review; } ////This is the GET that I'm trying to write, but don't know what to do // GET: api [Route("api/review/site")] [HttpGet] public IEnumerable<Review> FindStoreBySite(int SiteID) { return db.Review } ////This GET also works and was generated by VS. // GET: api/Review/5 [ResponseType(typeof(Review))] public IHttpActionResult GetReview(int id) { Review review = db.Review.Find(id); if (review == null) { return NotFound(); } return Ok(review); } 

Essentially what I'm aiming to do is to limit what's returned by the API to only the results where the SiteID is equal to whatever value is passed into the URL. I'm not even sure where to get started with this, and googling/searching stack overflow for "what to put in web api return" has been fruitless.

How do I tell the API what I want to have returned based off a parameter besides ReviewID?

Edit: I've updated the code per the suggestions in the answer below, but now I'm getting a new error.

Here's the current code:

 private ReviewAPIModel db = new ReviewAPIModel(); // GET: api/Review [Route("api/Review")] [HttpGet] public IQueryable<Review> GetReview() { return db.Review; } // GET: api [Route("api/Review/site/{siteid}")] [HttpGet] public IEnumerable<Review> FindStoreBySite(int siteid) { return db.Review.Where(Review => Review.SiteID == siteid); } // GET: api/Review/5 [ResponseType(typeof(Review))] public IHttpActionResult GetReview(int id) { Review review = db.Review.Find(id); if (review == null) { return NotFound(); } return Ok(review); } } 

Here's the error that I get:

Multiple actions were found that match the request 

When I google it, it takes me to this question: Multiple actions were found that match the request in Web Api

However, I've tried the answers there (I've confirmed that I'm using Web API V2, and my webapiconfig.cs file includes the config.MapHttpAttributeRoutes(); line.

In addition, as you can see in my code above, I've included the appropriate routing. However, I'm still getting an error telling me that it's returning two conflicting API calls.

2 Answers 2

1

To pass parameters to a WebApi controller you need to add a [Route()] attribute to that controller and mark the part of the link that's used as the attribute with this {}.

To return reviews that only match the passed in parameter you need to use LINQ to filter the data.

Here is an example:

[Route("api/getFoo/{id}")] public IHttpActionResult GetFoo(int id) { return db.Foo.Where(x => x.Id == id); } 

The {id} part of the string represents the id that will be in the url in your browser: http://localhost:51361/api/getFoo/2. The "2" in the url IS the {id} property that you marked in your [Route("api/getFoo/{id}")] attribute.

I also modified your code:

public class ReviewController : ApiController { ... [Route("api/review/site/{siteId}")] [HttpGet] public IEnumerable<Review> FindStoreBySite(int SiteID) { return db.Review.Where(review => review.Id == SiteID); } ... 

Your request url should look somewhat like this: http://localhost:51361/api/review/site?SiteID=2


This can be difficult to wrap your head around at first but you'll get used to it eventually. It's how arguments are passed to Controller Action parameters.

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

11 Comments

Right, that's exactly what I have in my sample code. I'm just not sure what goes in your ... in between the { }s. I have a working API that will return all reviews, and also an API that can limit reviews based off of review ID. I'm struggling to get it to return all reviews based off of SiteID instead of the "key" from the model class.
@phroureo I updated my answer. Basically you need to use LINQ to specify that you only want reviews whose Id property equals the passed in siteId property. You can do that by doing db.Reviews.Where(review => review.Id == siteId)
Thanks! That's what I was looking for. :)
@phroureo I'm glad to hear that. Thanks for the upvote and selected answer!
Okay, I lied. For some reason, .../api/review/site?id=1 is returning the same thing as /api/review/1. It's not looking at the siteID at all.
|
1

if you want to get parameters for GET, it's like a simple overload, but if it's done, POST is with [fromBody], because the URL is in the tag [Route ("/abc/123/{id}")]

example

code

[Route ("/abc/123/{idSite}")] [HttpGet] public HttpResponseMessage ControllerIdSite(int IdSite){ //CODE . . . return Request.CreateResponse<int>(HttpStatusCode.OK, IdSite); } 

call

 /abc/123/17 

return

 17 

OR

[Route ("/abc/123")] [HttpGet] public HttpResponseMessage ControllerIdSite(int IdSite){ //CODE . . . return Request.CreateResponse<int>(HttpStatusCode.OK, IdSite); } 

call

 /abc/123?IdSite=17 

return

 17 

1 Comment

Sorry, your answer isn't entirely clear to me. What would I put in your code so that it would know to look in the Review controller for reviews where the SiteID matches the parameter?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.