QueryString truncated in WebAPI RequestBody when request is manually composed? - asp.net-web-api

I've confirmed I have the dropdown set to post and the URL is correct, because the string gets passed into my Web API project without error. However it is cutting everything off of the string after the first parameter
Request Headers:
User-Agent: Fiddler
Host: localhost:52888
Content-Length: 35
Content-Type: application/x-www-form-urlencoded
Request Body:
=name=TestName&date=10/15/2014
In the Web API project the only part that is passed is name=Test Name
I'm confident the query string is in the right format. I'm wondering if anyone else can point me in the direction of what I might be missing.
If I remove the = in front of the request body then nothing is received

A signature like AddCourse([FromBody] string courseRequest) tells WebAPI to look for a POST parameter named courseRequest. But (when it is properly formatted) your request body doesn't have that parameter - instead it has name and date. When you misformat the request body by prepending an = character, it apparently causes the parser to decide that name=test is the value. But the second part of the query string is after an &, and is clearly a different parameter. It has nowhere to bind that parameter, so it just gets dropped.
There are at least two solutions here. One would be to pass the parameters on the query string instead of in the request body, and use a method signature like: AddCourse(string name, string date) (note removed of [FromBody]).
Another would be to create a model object that encapsulates the request, something like
public class AddCourseModel{
public string Name {get;set;}
public string Date {get;set;}
}
and use that as the argument to your method: AddCourse([FromBody] AddCourseModel model).

Related

Sending array of string from postman client

I am using web api with identity 2.0.
I want to assign multiple roles to a user.
I am using post man client to communicate with web api.
In api the method i used to get user id and roles for the user is given below:
public async Task<IHttpActionResult> AddRoleToUser(string userid,[FromUri] string[] selectedRoles)
Here selectedRoles is an array.
From postman client i am passing array as given below :
I am passing user id in the url.
Am i passing the array of roles in correct format from postman client?
The call to api was success ,but selectedRoles always contains null value.
I tried with raw json as given below,but it did not worked
If i can pass the roles as raw json,can any show an example
First problem: you're specifying that selectedRoles array comes from the URI (URL) with this attribute: [FromUri]. You need to remove this attribute, because you're sending it in the request body, not in the URL.
Web API actions can only receive a single parameter from the request body, and any number of parameters from the URL. So you need to pass the userid parameter as a query string parameter, like this ?userid=123123, and the other parameter in the body. (You could also create a route that includes a userid, or receive the userid as the id parameter and pass it as an URL segment, if you're using the deafult route)
You also need to specify in your headers the format of the information you're sending in the body. So you need to include this header: Content-Type: application/json, because you're including JSON in your request body.
Finally, as you're sending a single parameter from the body, you can send it like this:
['Admin', 'Employee']
If you want to use the format in your example, you shuould create a class to use as parameter in your action, that would look like this:
public class RoleList
{
public string[] selectedRoles { get; set; }
}
And your action should include this as parameter:
public async Task<IHttpActionResult>
AddRoleToUser(string userid, RoleList roleList)
method code in C#:
public void Put([FromBody]string[] selectedRoles)
{
foreach (var role in selectedRoles)
{
}
}
to call method in postman
in heading tab add your parameter and Content-type parameter with value application/x-www-form-urlencoded
in body tab select raw and JSON(application/json)
then in body box add your array like below:
['Admin', 'Employee']

Net Web API - How to pass a URL as input parameter on a Get

I am trying to pass a URL as a input parameter to a ApiController from an Angular REST call. The URL comes as a query string (this is a Provider Hosted app in SharePoint, I need the URL to query SP FWIW).
Here is the method signature in the ApiController:
// GET: api/ProjectSite/5
public IEnumerable<ProjectSite> Get(string id)
{
return ProjectSite.GetAllProjectSites(id);
}
And here is where I am making the call in Angular:
var spUrl = "'" + getParameterByName("SPHostUrl") + "'";
var queryUrl = "/api/ProjectSite/" + encodeURIComponent(spUrl);
return $http.get(queryUrl);
This generates a GET request that looks like this:
https://localhost:12345/api/ProjectSite/https%3A%2F%2Fcompany.sharepoint.com%2Fsites%2Fsite_dev%2Fweb
When I do I get 'HTTP 400 (Bad Request)' back. If I stop on a break point in the Angular code and change the input param to a simple string (e.g. 'asdf') the REST call is made and I see the Api is called. If I do not change the string and put a breakpoint inside the Get Api method the breakpoint is not reached, indicating that the code is blowing up somewhere in the route engine.
What I don't get is, while its encoded, the string I am trying to pass in should still be treated as a string, right? I also tried changing the input to Uri but that doesn't appear to work (and Uri isn't listed as a supported input type, anyways).
Anyone know how to pass a URL as input parameter?
Have you tried calling it using a query string?
var queryUrl = "/api/ProjectSite?id=" + encodeURIComponent(spUrl);

Web API 2 attribute routing returning 404

I'm having trouble getting the Web API 2 attribute routing to work.
I've been trying everything I could find this whole evening but I can't find the problem.
What I want to achieve is the following:
Make a POST request to http://localhost:xxxx/api/chat/joingroup/1234 to get to the following API call:
[Route("joingroup/{id}")]
[HttpPost]
public async Task<IHttpActionResult> JoinGroup(string id, string connectionID)
{
await hubContext.Groups.Add(connectionID, id);
return Ok(hubContext.Groups.ToString());
}
This keeps getting me a http 400 message.
{"message":"No HTTP resource was found that matches the request URI 'http://localhost:41021/api/chat/joingroup/123'.",
"messageDetail":"No action was found on the controller 'Chat' that matches the request."}
But sending a post to: http://localhost:41021/api/chat/sendmessage/pm/123123 and also to http://localhost:41021/api/chat/joingroup gives me a 200
The chatcontroller:
[RoutePrefix("api/chat")]
public class ChatController : ApiController
{
IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
[...]
[Route("joingroup/{id}")]
[HttpPost]
public async Task<IHttpActionResult> JoinGroup(string id, string connectionID)
{
await hubContext.Groups.Add(connectionID, id);
return Ok(hubContext.Groups.ToString());
}
HTTP POSTS to http://localhost:xxxx/api/chat/sendmessage are working fine.
I cannot figure out why it isn't going to the correct method when I'm calling a POST on http://localhost:xxxx/api/chat/joingroup/1234.
SOLUTION:
The solution was to reference both values that are needed in the JoinGroup method, id and connectionID. Now the request will hit this method.
Using:
http://localhost:xxxx/api/chat/joingroup/john?connectionid=123 will work.
I noticed two things on the code you sent through:
the path you POST to is: localhost:xxxx/joingroup/1234 , this
should be localhost:xxxx/api/chat/joingroup/1234
because you have 2 parameters for the joingroup, you will need to pass both of them through, may be like this localhost:xxxx/api/chat/joingroup/1234?connectionID=value or you can pass it on the request body
if the connectionID is optional you can modify the method to use option al parameters like this
public string JoinGroup(string id, string connectionID = "")
please let me know if this helps.
Thanks
Ashraf
I assume the connectionID parameter references the POSTed data. The easiest thing to make it work is to decorate it with the [FromBody] attribute and put an = in front of the value being sent like this: =MyConnection1.
Web API expects an object with properties or an array otherwise. Alternatively, you can wrap the connection ID with a custom class and pass it serialized as JSON/XML.

Pass URL containing a query string as a parameter ASP.Net Web API GET?

I'm trying to pass in an URL as a string parameter to a WEB API GET method.
The controller:
public class LinksController : ApiController
{
public HttpResponseMessage Get(string targetUrl)
{
//query db with targetURL
}
}
The aim is to query the database to see if the URL is stored. This works fine with simple URLs and URLs whose query string contains a single parameter, like:
http://www.youtube.com/watch?v=nLPE4vhSBx4
The problem I'm encountering is specifically when the query string contains multiple parameters, e.g.
http://www.youtube.com/watch?v=nLPE4vhSBx4&feature=youtube_gdata
When debugging, the value of targetUrl is only ".../watch?v=nLPE4vhSBx4" which means &feature=youtube_gdata is lost.
The GET request looks like this:
http://localhost:58056/api/links?targetUrl=http://www.youtube.com/watch? v=nLPE4vhSBx4&feature=youtube_gdata
I've also tried to add the following route in WebApiConfig.cs:
config.Routes.MapHttpRoute(
name: "Links",
routeTemplate: "api/links/{targetUrl}",
defaults: new { controller = "Links", targetUrl= RouteParameter.Optional }
);
But the GET request then results in 400 Bad Request.
So my question is, can't this be done? I would like the complete URL! Or would I need to change the method header to use the [FromBody] attribute and pass it as a JSON object?
You should URLEncode your target URL parameter so that it doesn't get mistaken for subsequent query string parameter. This means the URL you specified should appear as:
http://localhost:58056/api/links?targetUrl=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DnLPE4vhSBx4%26feature%3Dyoutube_gdata
And then inside your Get method, URLDecode the string that is passed as a parameter.
Both methods can be found in System.Web.HttpUtility

Web API - JObject from URI

Web API allows me to capture the body of a POST request in a JObject:
$.post('/api/Query/DoSomething', { Foo: "one", Bar: 4 });
public string Post(JObject data)
{
// data is populated
}
However the same technique does not work with a get request and URI parameters.
$.get('/api/Controller', { Foo : "one", Bar : 4 });
public string Get([FromUri]JObject data)
{
// data is empty
}
Any workaround here?
It doesn't work because a GET request does not have a body, and hence no content type. Therefore, Web API does not know that you have JSON in your URL. You have a few choices:
Pass your data as query string parameters, as is traditionally done in GET requests, and change your method to accept those parameters individually, or in a regular class (POCO).
Change your GET method to accept a string instead of a JObject, then use JSON.Net to deserialize it manually, e.g. JObject obj = JObject.Parse(data);
If you're feeling ambitious, you might be able to implement a custom binder to do this.
My recommendation is option 1. Traditionally, a GET method is just intended to look something up, so you really should only be passing IDs and simple query options anyway. It is unusual to be passing JSON data in a URL. Also the length of URLs can be limited by some browsers. If you find you are needing to pass JSON data, use POST (or PUT) instead.
You can create an object and bind to it using the FromUri.
Check out this solution which I am using https://stackoverflow.com/a/49632564/2463156.

Resources