how to pass parameters to asp.net web api get method? - c#

Following is my get method in ASP.NET Web API.
[HttpGet]
public IHttpActionResult GetDetails([FromBody] RetrieveDetails eDetails)
{}
following is the class
public class RetrieveDetails
{
public string name{ get; set; }
public string Type { get; set; }
}
When I try to call GetDetails from Fiddler eDetails is always null.
http://localhost:101222/api/emailservice/GetDetails?name=testname&Type=testtype
I tried different methods but the value is always null.
If I change [HttpGet] to [HttpPost] and add the request body its working fine. But I need get method.

Do you need [FromBody] there if you are passing values in URL for GET. You should be using [FromUri] if you are passing values in querystring.
https://learn.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

Related

How can I bind simple type coming from body of the request in ASP.NET Core 5 Web API

I tried to send a JSON object with the same name that action argument has but It seems not working I don't know what I did wrong.
My question is how to bind simple types like the example shown, without the need to create complex type that wrap my value property?
Action
public IActionResult Test([FromBody] string value)
{
}
PostMan : raw > JSON
{
"value":"testValue"
}
public class MyRequest {
public string Value { get; set; }
}
//controller
IActionResult Test([FromBody] MyRequest request)
This should do the job.
The class/type related to the frombody object should match the whole json object and not only one property of it
This cannot work with GET requests, so try a POST

Model value redirected to another action does not pass all values

I have an ASP.Net Core application which needs passing of a model from one action to another.
These are models :
public class ClassA
{
public string Id{get;set;}
public string Name {get;set;}
public StudentMarks Marks {get;set;}
}
public class StudentMarks
{
public int Marks {get;set;}
public string Grade {get;set;}
}
And the post Controller:
[HttpPost]
public ActionResult TestAction1(ClassA model)
{
return RedirectToAction("TestAction2", model);
}
public ActionResult TestAction2(ClassA model)
{
}
In TestAction 1 while debugging, i see that Id, Name and marks have value.
I am getting the value for Id in TestAction2 same as that in TestAction1. However the value of complex object Marks is not obtained in the TestAction2 action method.
What are my other options?
You cannot redirect with a model. A redirect is simply an empty response with a 301, 302, or 307 status code, and a Location response header. That Location header contains the the URL you'd like to redirect the client to.
The client then must make a new request to that URL in the header, if it so chooses. Browsers will do this automatically, but not all HTTP clients will. Importantly, this new request is made via a GET, and GET requests do not have bodies. (Technically, the HTTP spec allows for it, but no browser or HTTP client out there actually supports that.)
It's unclear what your ultimate goal is here, but if you need to persist data temporarily between requests (such as a redirect), then you should serialize that data into a TempData key.
You can use TempData to pass model data to a redirect request in Asp.Net Core In Asp.Net core, you cannot pass complex types in TempData. You can pass simple types like string, int, Guid etc. If you want to pass a complex type object via TempData, you have can serialize your object to a string and pass that. I have made a simple test application that will suffice to your needs:
Controller:
public ActionResult TestAction1(ClassA model)
{
model.Id = "1";
model.Name = "test";
model.Marks.Grade = "A";
model.Marks.Marks = 100;
var complexObj = JsonConvert.SerializeObject(model);
TempData["newuser"] = complexObj;
return RedirectToAction("TestAction2");
}
public ActionResult TestAction2()
{
if (TempData["newuser"] is string complexObj )
{
var getModel= JsonConvert.DeserializeObject<ClassA>(complexObj);
}
return View();
}
Model:
public class ClassA
{
public ClassA()
{
Marks = new StudentMarks();
}
public string Id { get; set; }
public string Name { get; set; }
public StudentMarks Marks { get; set; }
}
public class StudentMarks
{
public int Marks { get; set; }
public string Grade { get; set; }
}
If you want to persist your TempData values for more requests you can use Peek and Keep functions. This answer can give more insight on these functions.
I think you're getting model and routeValues mixed up. The overload of RedirectToAction that you're calling (takes a string and an object) expects a routeValues argument, not a model argument. https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.redirecttoaction?view=aspnetcore-2.2
TestAction1 is called via Post, but TestAction2 is called via Get. You need to work out a URL that will let you call TestAction2 the way you want (independently of the RedirectToAction in TestAction1). I'm guessing this will involve setting up a custom route. Once you have a URL that will let you call TestAction2 the way you want, you can specify the route values to form that URL in the RedirectToAction in TestAction1.
I think the problem is that you shuold use:
return RedirectToAction("TestAction2", model);
(you did this without return)

How do I handle path/route parameters in Swashbuckle?

I have a controller where I get the ID from the route.
[HttpGet]
[Route("{vehicleId}")]
public InfoDto GetInfo([FromUri] VehicleDetailsRequest request)
{
return ...;
}
The VehicleDetailsRequest object looks like this (the Validator is from FluentValidation):
[Validator(typeof(VehicleDetailsRequestValidator))]
public class VehicleDetailsRequest
{
public int VehicleId { get; set; }
public string Lang { get; set; }
}
I can query this action as I expect with http://localhost/controller/123?lang=sv but my swagger documentation looks like this:
How can I get Swashbuckle/Swagger to only show me one vehicleId but still keep the FluentValidation?
I'm using Swashbuckle 5.6 and .Net Framework 4.6.2.
In my opinion, there is something wrong with action method signature.
The parameter from the URL should be present in the action method parameters.
Also, if you want only lang in query string, then it should also be present as a parameter in the action.
Please note that if you specify object in the action parameters, all its properties would be forming the query string.
So, your action method should like below:
[HttpGet]
[Route("{vehicleId}")]
public InfoDto GetInfo(int vehicleId, [FromUri] string lang)
{
return ...;
}
This should help you to resolve the issue.

ASP.Net Core Web API Controller action with many parameters

I have ASP.Net Core Web API Controller's method that returns List<Car> based on query parameters.
[HttpPost("cars")]
public async Task<List<Car>> GetCars([FromBody] CarParams par)
{
//...
}
Parameters are grouped in record type CarParams. There are about 20 parameters:
public class CarParams
{
public string EngineType { get; set; }
public int WheelsCount { get; set; }
/// ... 20 params
public bool IsTruck { get; set; }
}
I need to change this method from POST to GET, because I want to use a server-side caching for such requests.
Should I create a controller's method with 20 params?
[HttpGet("cars")]
public async Task<List<Car>> GetCars(string engineType,
int wheelsCount,
/*...20 params?...*/
bool isTruck)
{
//...
}
If this is the case: Is there a way to automatically generate such a complex URL for a client-side app?
You can keep the model. Update the action's model binder so that it knows where to look for the model data.
Use [FromQuery] to specify the exact binding source you want to apply.
[HttpGet("cars")]
[Produces(typeof(List<Car>))]
public async Task<IActionResult> GetCars([FromQuery] CarParams parameters) {
//...
return Ok(data);
}
Reference Model Binding in ASP.NET Core
Just change [FromBody] attribute with [FromUrl]

Web API Post with multi parameter never work

How can we support ajax post?
This the server code:
[RoutePrefix("api/Dashboard")]
public class PatientDashboardController : ApiController
{
[Route("UpdatePatientById")]
[HttpPost]
public IHttpActionResult UpdatePatientById(int? pk, string name, object value )
{
return Ok(name);
}
}
This is what I post to the server
Request URL:http://localhost/mydomain/api/Dashboard/UpdatePatientById
Request Method:POST
name:sex
value:1
pk:1093
I'm using x-editable plugin on the front end, it does the ajax post automatically. I don't think there is anything wrong with the post url.
This the error it gives me:
"No HTTP resource was found that matches the request URI 'http://example.com/mydomain/api/Dashboard/UpdatePatientById'."
MessageDetail: "No action was found on the controller 'Dashboard' that matches the request."
Web API can only receive one parameter from the body so you'll have to specify it as a type that aggregates those fields.
class PatientParameters
{
public int? Pk { get; set; }
public string Name { get; set; }
public object Value { get; set; }
}
and pass that:
public IHttpActionResult UpdatePatientById([FromBody] PatientParameters parameters) { }

Categories