ChatGPT解决这个技术问题 Extra ChatGPT

How should I pass multiple parameters to an ASP.Net Web API GET?

I am using the .Net MVC4 Web API to (hopefully) implement a RESTful api. I need to pass in a few parameters to the system and have it perform some action, then return a list of objects as the results. Specifically I am passing in two dates and returning records that fall between them. I'm also keeping track of the records returned so that subsequent calls do not get reprocessed in the system.

I've considered a few approaches:

Serializing the params into one single JSON string and picking it apart in the API. http://forums.asp.net/t/1807316.aspx/1 Pass the params in the query string. What is best way to pass multiple query parameters to a restful api? Defining the params in the route: api/controller/date1/date2 Using a POST that inherently lets me pass an object with params. Researching ODATA since the Web API (currently) supports it. I haven't done much with this yet so I'm not very familiar with it.

It seems that proper REST practices indicate when data is pulled, you should use a GET. However, GET should also be nullipotent (produces no side-effects), and I wonder if my specific implementation violates that since I mark records in the API system, hence I am producing side-effects.

It also led me to the question of supporting variable parameters. If the input parameter list changes, it would be tedious to have to re-define your route for Choice 3 if that happens a lot. And what might happen if the parameters are defined at run-time...

In any case, for my specific implementation, which choice (if any) seems best?


M
Mark Pieszak - Trilon.io

I think the easiest way is to simply use AttributeRouting.

It's obvious within your controller, why would you want this in your Global WebApiConfig file?

Example:

    [Route("api/YOURCONTROLLER/{paramOne}/{paramTwo}")]
    public string Get(int paramOne, int paramTwo)
    {
        return "The [Route] with multiple params worked";
    }

The {} names need to match your parameters.

Simple as that, now you have a separate GET that handles multiple params in this instance.


This is great. Most people recommend setting up the route in the WebApiConfig file, but this is indeed nicer.
Indeed, we (most people) do recommend having a centralized management area for your config. In the case of Web APIs (Microsoft or otherwise), centralized patterns for REST are key. Attribute routing is cute, but it makes one-off exceptions far too tempting.
Agreed, I need to update my answer actually. There's a much better way of doing multiple parameters with GETs. Posted this when I was newer to WebAPI, now I don't use AttributeRouting (unless I just don't want to create a new Controller), and pass all the Parameters in the QueryString, they map automatically. Updating when I get a chance so people don't use this older method
Is there a way to set a Route for named parameters (e.g. query parameters)?
If action method name is required, this can be modified to accommodate so. [Route("api/YOURCONTROLLER/Get/{paramOne}/{paramTwo}")] public string Get(int paramOne, int paramTwo) { return "something"; }
E
Evan Mulawski

Just add a new route to the WebApiConfig entries.

For instance, to call:

public IEnumerable<SampleObject> Get(int pageNumber, int pageSize) { ..

add:

config.Routes.MapHttpRoute(
    name: "GetPagedData",
    routeTemplate: "api/{controller}/{pageNumber}/{pageSize}"
);

Then add the parameters to the HTTP call:

GET //<service address>/Api/Data/2/10 

This seems to be the only answer that lists all the parts. I wish that someone better described how to use the api/controller?start=date1&end=date2 style URI.
@Hot Licks Andrew Veriga's answer works well with query string arguments. Essentially, you bind the query string names to class properties and pass them into your method. Your method will take a single class argument marked with the [FromUri] attribute and will have your query string arguments as its properties.
Great stuff. Thanks!
hi @HotLicks and GrahamWright do you think you can answer this question? Thanks, stackoverflow.com/questions/57565318/…
C
Community

I just had to implement a RESTfull api where I need to pass parameters. I did this by passing the parameters in the query string in the same style as described by Mark's first example "api/controller?start=date1&end=date2"

In the controller I used a tip from URL split in C#?

// uri: /api/courses
public IEnumerable<Course> Get()
{
    NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
    var system = nvc["System"];
    // BL comes here
    return _courses;
}

In my case I was calling the WebApi via Ajax looking like:

$.ajax({
        url: '/api/DbMetaData',
        type: 'GET',
        data: { system : 'My System',
                searchString: '123' },
        dataType: 'json',
        success: function (data) {
                  $.each(data, function (index, v) {
                  alert(index + ': ' + v.name);
                  });
         },
         statusCode: {
                  404: function () {
                       alert('Failed');
                       }
        }
   });

I hope this helps...


I guess you're not using WebApi because ParameterBinding will map your querystring to your api method parameters automagically...
Yes, a better way would be to use and attribute like [Route("api/DbMetaData/{system}/{searchString}")] and then add there paramters to the Get(string system, string searchString) and then call with "...api/DbMetaData/mysystem/mysearchstring"
I used his example in my C# MVC WebApi and it worked fine. +1 for example
A
Andrew Veriga

I found exellent solution on http://habrahabr.ru/post/164945/

public class ResourceQuery
{
   public string Param1 { get; set; }
   public int OptionalParam2 { get; set; }
}

public class SampleResourceController : ApiController
{
    public SampleResourceModel Get([FromUri] ResourceQuery query)
    {
        // action
    }
}

The clue here is the [FromUri]
Though the article is in Russian, @tranceporter is right. The "FromUri" looks like a great way to get the parameters from the url. Another article that might be helpful: asp.net/web-api/overview/formats-and-model-binding/…
This is what I've been doing for quite a while now and it's worked great! I'd also recommend this solution.
If you call into another helper method (not the Get), can you still use [FromUri]? I can't seem to get that to work.
i
its4zahoor

What does this record marking mean? If this is used only for logging purposes, I would use GET and disable all caching, since you want to log every query for this resources. If record marking has another purpose, POST is the way to go. User should know, that his actions effect the system and POST method is a warning.


By marking I mean simply tracking which records are processed and returned so that subsequent calls don't repeat them. In my case I'm just making an insert into another table to track which are processed.
Right now I do have it implemented as a POST mainly for the reason you said--actions happen and the consumer is aware of them. Plus it seems easy and most flexible with resp to passing different data in.
@sig606: POST is the way to go for me, but your protocol doesn't seem to be safe. What if something happens and records are retrieved on client side, but not processed due to a bug? You won't return them any more and client is left with lost data.
Right now my API only returns records after they were processed. So the consumer passes the API two dates. Records between those two dates are processed and marked. Then the data is returned to the caller. I suppose if something happens during the processing or after processing before reaching the client, I have a problem.
V
VJAI

Using GET or POST is clearly explained by @LukLed. Regarding the ways you can pass the parameters I would suggest going with the second approach (I don't know much about ODATA either).

1.Serializing the params into one single JSON string and picking it apart in the API. http://forums.asp.net/t/1807316.aspx/1

This is not user friendly and SEO friendly

2.Pass the params in the query string. What is best way to pass multiple query parameters to a restful api?

This is the usual preferable approach.

3.Defining the params in the route: api/controller/date1/date2

This is definitely not a good approach. This makes feel some one date2 is a sub resource of date1 and that is not the case. Both the date1 and date2 are query parameters and comes in the same level.

In simple case I would suggest an URI like this,

api/controller?start=date1&end=date2

But I personally like the below URI pattern but in this case we have to write some custom code to map the parameters.

api/controller/date1,date2

Actually, those were my orig explanations. I think LukLed shined up my tags and URL link.
As far as SEO, in this case it wouldn't apply. This code will be "server-to-server", so I wouldn't care if the outside world ever discovered it. In fact, I have to make sure proper security steps are taken to avoid random access. I've had to do the JSON serialization for another part of the system (seems to be a bug trying to POST large lists of obj so I had to serialize to string), so it wouldn't be much of a stretch in this case.
I hope you already have answers then why you are asking question?
Sorry for this late response, Mark. I had tried a few solutions but wasn't sure which was the best and was trying to stick with industry-standard approaches, so I posted here at SO.
@Mark Something like to the next: stackoverflow.com/questions/9681658/…?
a
ashwath hegde
 [Route("api/controller/{one}/{two}")]
    public string Get(int One, int Two)
    {
        return "both params of the root link({one},{two}) and Get function parameters (one, two)  should be same ";
    }

Both params of the root link({one},{two}) and Get function parameters (one, two) should be same


R
Rick Riggs

I know this is really old, but I wanted the same thing recently and here's what I found...

    public HttpResponseMessage Get([FromUri] string var, [FromUri] string test) {
        var retStr = new HttpResponseMessage(HttpStatusCode.OK);
        if (var.ToLower() == "getnew" && test.ToLower() == "test") {
            retStr.Content = new StringContent("Found Test", System.Text.Encoding.UTF8, "text/plain");
        } else {
            retStr.Content = new StringContent("Couldn't Find that test", System.Text.Encoding.UTF8, "text/plain");
        }

        return retStr;
    }

So now in your address/URI/...

http(s)://myURL/api/myController/?var=getnew&test=test

Result: "Found Test"

http(s)://myURL/api/myController/?var=getnew&test=anything

Result: "Couldn't Find that test"


I personally like this style in C#, because I can change the signature of the original method, and overload exactly what I am trying to accomplish, without tweaking the routing configs. Hope it helps others who are used to this (maybe antiquated) approach of making a GET request.
I've had to create an event API that's consumed by a third party calendar app, which uses this approach. I'm glad I found this answer!
R
RaZor1994

Now you can do this by simply using

        public string Get(int id, int abc)
        {
            return "value: " + id + "  " + abc;
        }

this will return: "value: 5 10"

if you call it with https://yourdomain/api/yourcontroller?id=5&abc=10


J
Jesse Mwangi
    public HttpResponseMessage Get(int id,string numb)
    {
        //this will differ according to your entity name
        using (MarketEntities entities = new MarketEntities())
        {
          var ent=  entities.Api_For_Test.FirstOrDefault(e => e.ID == id && e.IDNO.ToString()== numb);
            if (ent != null)
            {
                return Request.CreateResponse(HttpStatusCode.OK, ent);
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Applicant with ID " + id.ToString() + " not found in the system");
            }
        }
    }

S
Sinji Yang

This code works for me. Then I can use the regular querystring on the url http://.../api/GetSomething?paramOne=1¶mTwo=2

.NET 6 Core

[Route("api/GetSomething")]
public IActionResult GetSomething(int paramOne, int paramTwo)
{
    ...    
    return Content(jsonData);
}

instead of doing the following [Route("api/GetSomething/{paramOne}/{paramTwo}")]