How to pass object to Web API as Parameter with HttpGet - c#

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

Related

How to create Single Custom Action Filter in asp.net core to validate GET & POST request parameters?

Want to create 'Custom Action Filter' in asp.net core, which basically performs some validation logic on the incoming GET & POST request related input parameters then throw validation exception if validation fails or allow the execution to proceed further on validation success.
Is it possible to create one single 'Custom Action Filter' to validate GET & POST request parameters with out using 'if else'(like sample mentioned below)? As you all know usually parameter comes as part of query string for GET request whereas parameter comes as part of request body for POST request
Considering SRP principle, I don't want to create input parameter validation code as part of controller/action logic code.
I can't use Model validation in my case.
public class MyModel
{
public string id{ get; set; }
public string orderId{ get; set; }
}
[HttpPost]
public async Task<IActionResult> Login([FromBody] MyModel model)
{
}
[HttpGet]
public async Task<IActionResult> GetAsync(string id, string orderId)
{
}
public class Validate : ActionFilterAttribute
{
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
if (context.HttpContext.Request.Method == "GET" )
{
//consider parameters from query string
//parameter validation logic
}
if (context.HttpContext.Request.Method == "POST" )
{
//consider parameters from body
//parameter validation logic
}
}
}

Sending data from DataTables to Web API controller using POST method

I try to make server-side processing for DataTables using Web API. There are two actions in my Web API controller with same list of parameters:
public class CampaignController : ApiController
{
// GET request handler
public dtResponse Get(int draw, int start, int length)
{
// request handling
}
// POST request handler
public void Post(int draw, int start, int length)
{
// request handling
}
}
If I use GET method to send AJAX request to the server, the Get action is activated. However, if I use POST method, then neither action are activated.
I tried to change POST handler signature to
public void Post([FromBody]object value)
{
// request handling
}
In this case the value is null. Note, the HttpContext.Current.Request.Form collection isn't empty. The draw, start, length variables are exist in this collection. Thus, I think the trouble is in model binding, but I cannot fix it. Help me, please.
Not knowing exactly what's going on, but appears there are a few missing elements. I've written a Post endpoint this morning, So hopefully will help pushing you in the right direction.
Also to note if you want "Data" use Get, if your inserting data then POST
[HttpPost]
[Route("orders")]
public async Task<IHttpActionResult> Post([FromBody]List<Models.Model.Order> orders)
{
if (orders == null)
return BadRequest("Unusable resources.");
if (validatedOrders.Count <= 0)
return BadRequest("Unusable resources.");
try
{
//Create abstracted Identity model to pass around layers
var identity = User.Identity as ClaimsIdentity;
var identityModel = IdentityModel.Create(identity);
if (identityModel == null)
return StatusCode(HttpStatusCode.Forbidden);
var response = await _orderService.AddAsync(validatedOrders, identityModel);
return Ok(response);
}
catch (System.Exception ex)
{
return InternalServerError();
}
finally
{
_orderService.Dispose();
}
}
Utilizing IHttpActionResult will expose the returning of a response
Verb attributes helps with building/designing Restful API's and same
name signatures
Attribute Routing saves writing in the config and change routes in
the class
To wrap it all up, replace the order collection with:
public sealed class Diagram
{
public int Draw { get; set; }
public int Start { get; set; }
public int Length { get; set; }
}
Rewrite the validation, remove the Identity creation, remove the insert and remove/replace the attribute routing.
With HttpContext.Current.Request.Form Try building a Diagram object from that and passing it up.
OR Alternatively passing in a form collection
[HttpPost]
[Route("something")]
// POST api/<controller>
public async Task<HttpResponseMessage> Post(FormDataCollection form)
{
string tid = form.Get("tid");
string sid = form.Get("sid");
string userid = form.Get("userid");
string udid = form.Get("udid");
}
Additional resource from the DataTable Docs
Git Hub Repo
What about this:
[HttpPost]
public void Post([FromBody]int draw, [FromBody]int start, [FromBody]int length)
{
// request handling
}

How to fix - The requested resource does not support http method 'POST'

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")]

Why does the Web API controller get null data from client through POST request?

I have an AngularJS app sending an object array to a Web API controller method through a POST request. On the server I have the following method definition:
[HttpPost]
[Route("Active")]
public async Task<IHttpActionResult> Post(IList<Media> mediaFiles)
{
try
{
foreach (var file in mediaFiles)
{
await Task.Factory.StartNew(() => PublicData.SetInactiveMedia(file.Id, file.Active));
}
return Ok();
}
catch (ArgumentException e)
{
return BadRequest(e.Message);
}
}
I use the $resource factory in order to interact with the server (but I have to mention that I have also tried with $http and no difference showed up). This is the method:
var activeMedia = $resource('/api/adminhotspotsmedia/active', { save: { method: 'POST' } });
var setActiveMedia = function (mediaFiles) {
activeMedia.save(mediaFiles);
}
The mediaFiles variable is an array of objects that absolutely match the Media model on the server.
In the Developer's Console I can see this Request Payload associated with the request:
So the array is trying to get to the server, but it cannot. The server gets a null value for the list of objects. I will add that I have tried using:
[FromBody] tag
dynamic instead of IList<Media>
IList<object> instead of IList<Media>
The problem persists. What could it be?
By default the model binder wont know what to do with the interface unless you have a custom model binder that knows what to expect and what the desired behavior is.
Alternatively you can use an actual List<Media>
[HttpPost]
[Route("Active")]
public async Task<IHttpActionResult> Post(List<Media> mediaFiles) { ... }
or array Media[]
[HttpPost]
[Route("Active")]
public async Task<IHttpActionResult> Post(Media[] mediaFiles) { ... }

webapi httppost sending the parameter as object

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)

Categories

Resources