I tried to use method overloading in C# WebApi
[HttpPost]
public HttpResponseMessage UpdateUser(PersonalInfoModel personalInfo){}
[HttpPost]
public HttpResponseMessage UpdateUser(RolesModel roles){}
On the client I call:
/UpdateUser(json)
let say we want to update the user personal info, so the json will look like:
{firstName: "testUser", lastName: "testUser", age: 20}
and it should match the PersonalInfoModel that looks like this:
public class PersonalInfoModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
My idea was to update different parts of the user information and to keep
it clear, meaning call the same method with a different object and I thought
UpdateUser on the server will know what function to use and it failed
because the server didn't know what route to use.
Next thing I tried to do is to call only One route in the server like this:
[HttpPost]
public HttpResponseMessage UpdateUser(dynamic obj){
return Update(obj);
}
public Update(PersonalInfoModel personalInfo){}
public Update(RolesModel roles){}
The above also didn't work with the error:
"The best overloaded method match for has some invalid arguments"
I tried to look on google but with no success to overcome this.
Try this
[HttpPost]
[Route("/api/[controller]/personalInfo")]
public HttpResponseMessage UpdateUser(PersonalInfoModel personalInfo){}
[HttpPost]
[Route("/api/[controller]/roles")]
public HttpResponseMessage UpdateUser(RolesModel roles){}
You need to use Route Attribute to differentiate between these methods for client to call.
[Route("api/Update")]
public class UpdateController
{
[Route("PersonalInfo")]
[HttpPost]
public HttpResponseMessage UpdateUser(PersonalInfoModel
personalInfo){}
[Route("Roles")]
[HttpPost]
public HttpResponseMessage UpdateUser(RolesModel roles){}
}
Then client calls api/Update/PersonalInfo to call first method and
api/Update/Roles to call second method
Hope this helps.
Related
I am working on .NET 6.0 Web API application. I need to pass object which is collection of string list to API with the purpose it will return data. I can do with HttpPost but since I am designing this API for the purpose of Get Record, what will be the right approach?
public class JobRoleDataView
{
public JobRoleDataView() { }
public List<string> Roles { get; set; }
}
this object will get more properties soon so it is not just List...
[HttpGet("SearchRecord")]
public async Task<IActionResult> SearchRecord(JobRoleDataView JobRoles)
{
//remaining code
return Ok(returnResponse);
}
error
TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body.
You can use [FromQuery] attribute and pass roles as querystring.
[HttpGet("SearchRecord")]
public async Task<IActionResult> SearchRecord([FromQuery]JobRoleDataView JobRoles)
{
//remaining code
return Ok(returnResponse);
}
}
The request url will be seen as below.
https://localhost:7009/WeatherForecast/SearchRecord?Roles=vishal&Roles=michel
I have a controller as
[ApiController]
[Route("api/getData/")]
and the GET method with route
[HttpGet("{name}/{message}/{num}")]
{
public async GetAsync(string name, string message,int num) {some code}
}
Now I also want to send 'message' as optional without changing the route and set it to default value of empty string in the method. So I am using both these functions now, independently they both work fine but not together.
[HttpGet("{name}/{num}/{message?}")]
{
public async GetAsyncOptional(string name, int num , string message="") {some code}
}
But I keep getting the error in StartUp.cs in
app.UseEndpoints(endpoint => {endpoint.MapController();
System.ArgumentException:'An optional parameter cannot have default value.(Parameter 'route template')
your two routes are overlapped, you have to give action name to separate them
[HttpGet("/~api/getDataOptional/{name}/{num}/{message?}")]
public async Task<ActionReslt> GetAsyncOptional(string name, int num , string message="")
{
...
}
or I don't see why dont' use one route for two, only if a query string parameters order is very important for you.
I can advise you to make class for request like, because you approach in answer seems like bad:
1)
class RequestData
{
string Name {get;set;}
int Age {get;set;}
string Message {get;set;}
}
Then make your controller:
[ApiController]
[Route("api/data")]
public class DataController {}
And method is:
3)
[HttpGet]
public async Task<ActionResult> GetAsyncOptional([FromBody] RequestData data)
{
//
}
That's more complex because if you extend your format for 4 and 5 argument, you will change your route one more time, It is not necessary. Optional params can be in request body.
There something very basic i must be missing which i cant understand what it is.
I have a method at the controller
[Route("SomeMethod")]
[HttpPost]
public IActionResult SomeMethod([FromBody]int interval)
{
...
}
And im seing with postman post request {"interval": 2000 }, The interval at the controller is not initialized. If i change the method paramater to be object i get ValueKind = Object : "{"interval": 2000 }"
I also tried the parameter to be string and then the body i sent is {"interval": "2000" }, And at the controller i get null
Based on this question i tried:
[Route("SomeMethod")]
[HttpPost]
public IActionResult SomeMethod([FromBody]JsonElement interval)
{
...
}
And got ValueKind = Undefined : "" At the contoroller, And also:
services.AddControllers()
.AddNewtonsoftJson();
When the method expects an int and got 0
According to documentation you have to pass it in request body as it is, just a value, without property name. But its imposible to bind more then one parameter. Anyway, I would reccomend to use proper object to bind body parameters.
[Route("SomeMethod")]
[HttpPost]
public IActionResult SomeMethod([FromBody]Request request)
{
return Ok();
}
public class Request
{
public int Interval { get; set; }
}
Below is WebAPI action. On googling about the below error:-
The requested resource does not support http method 'POST'
I got number of links & updated my api accordingly but still I am getting the same error.
Web api not supporting POST method
ASP.NET Web Api: The requested resource does not support http method 'GET'
[AcceptVerbs("POST")]
[HttpPost]
[Route("rename/{userId}/{type}/{title}/")]
public IHttpActionResult Rename([FromBody] int userId, [FromBody] string type, [FromBody] string title)
{
//my api stuff
}
But still when calling the above via post man throws the error.
How do I get rid of this error??
Also is it possible to fix this without using [FromBody] attribute in the method parameters list?
Any help/suggestion highly appreciated.
Thanks.
You have declared route which requires url parameters
[Route("rename/{userId}/{type}/{title}/")]
So when you send request to api/customer/rename it does not match this method. You should remove parameters which you are passing in request body from route parameters
[Route("rename")]
Make sure that you have appropriate RoutePrefix("api/customer") attribute on your controller.
Second problem is multiple [FromBody] parameters. You will get can't bind multiple parameters error. There is limitation - you can mark only one parameter as FromBody. See Sending Simple Types notes:
Web API reads the request body at most once, so only one parameter of
an action can come from the request body. If you need to get multiple
values from the request body, define a complex type.
You should create complex type which will hold all parameters
public class RenameModel
{
public int UserId { get; set; }
public string Type { get; set; }
public string Title { get; set; }
}
And change method signature to
[HttpPost]
[Route("rename")]
public IHttpActionResult Rename(RenameModel model)
And send request data as application/x-www-form-urlencoded
[Route("rename/{userId}/{type}/{title}/")]
public IHttpActionResult Rename([FromBody] int userId, [FromBody] string type, [FromBody] string title)
The last answer is correct, you're asking for these parameters in the route, but saying that you expect them in the post body. Also, usually the route would begin with a noun rather than a verb. What is it you're renaming? (i.e. [Route("users/rename/{userId}/{type}/{title}")]
Based on your initial post, try this instead:
[HttpPost]
[Route("rename/{userId}/{type}/{title}" Name = "RenameUser"]
public IHttpActionResult Rename(int userId, string type, string title)
{
_myServiceMethod.Rename(userId, type, title);
return new StatusCodeResult(HttpStatusCode.Created, this);
}
Or, if you wanted to do a post with the info in the body:
Declare your data contract:
public class User
{
public string Type { get; set; }
public string Title { get; set; }
}
Then on the endpoint:
[HttpPost]
[Route("rename/{userId}", Name = "RenameUserPost")]
public IHttpActionResult RenameUserPost(int userId, [FromBody] User userData)
{
return new StatusCodeResult(HttpStatusCode.Created, this);
}
Note that in both returns 'this' refers to your controller class that inherits from ApiController. Verified both of these in swagger, and they accept POSTs and return status codes.
Hope this helps.
I had this error for wrong string in Route string on top of my action.
[Route("api/TestReaderPercentStudyHomework/AddOrUpdate")]
I have a webapi method as httppost as shown below. I am trying to make a request using
fiddler but I cant get param object. It is null if I send the request as shown in the image. what am I doing wrong?
[ActionName("getCustomerByName")]
[HttpPost]
public async Task<List<Customer>> GetcustomerByName(object param)
{
}
What do you expect object param to be?
Does the request body JSON string represent a Customer ?
If yes, use Customer as the type instead of object eg
public async Task<List<Customer>> GetCustomerByName(Customer param)
If no then define a class (Any name) with the same field names as the JSON string you are passing and use that class instead of object eg
public class QueryArgs
{
public int Id { get; set; }
// rest of your fields go here
}
public async Task<List<Customer>> GetCustomerByName(QueryArgs param)