Reading FromUri and FromBody at the same time
Asked Answered
D

3

27

I have a new method in web api

[HttpPost]
public ApiResponse PushMessage( [FromUri] string x, [FromUri] string y, [FromBody] Request Request)

where request class is like

public class Request
{
    public string Message { get; set; }
    public bool TestingMode { get; set; }
}

I'm making a query to localhost/Pusher/PushMessage?x=foo&y=bar with PostBody:

{ Message: "foobar" , TestingMode:true }

Am i missing something?

Dribble answered 22/8, 2012 at 11:39 Comment(0)
R
33

A post body is typically a URI string like this:

Message=foobar&TestingMode=true

You have to make sure that the HTTP header contains

Content-Type: application/x-www-form-urlencoded

EDIT: Because it's still not working, I created a full example myself.
It prints the correct data.
I also used .NET 4.5 RC.

// server-side
public class ValuesController : ApiController {
    [HttpPost]
    public string PushMessage([FromUri] string x, [FromUri] string y, [FromBody] Person p) {
        return p.ToString();
    }
}

public class Person {
    public string Name { get; set; }
    public int Age { get; set; }

    public override string ToString() {
        return this.Name + ": " + this.Age;
    }
}

// client-side
public class Program {
    private static readonly string URL = "http://localhost:6299/api/values/PushMessage?x=asd&y=qwe";

    public static void Main(string[] args) {
        NameValueCollection data = new NameValueCollection();
        data.Add("Name", "Johannes");
        data.Add("Age", "24");

        WebClient client = new WebClient();
        client.UploadValuesCompleted += UploadValuesCompleted;
        client.Headers["Content-Type"] = "application/x-www-form-urlencoded";
        Task t = client.UploadValuesTaskAsync(new Uri(URL), "POST", data);
        t.Wait();
    }

    private static void UploadValuesCompleted(object sender, UploadValuesCompletedEventArgs e) {
        Console.WriteLine(Encoding.ASCII.GetString(e.Result));
    }
}
Rebus answered 22/8, 2012 at 11:48 Comment(13)
It is true only if I use mvc structure. However this is web api so the binding is different than mvc. But thanks for your reply!Dribble
Ensure that the HTTP header contains Content-Type: application/x-www-form-urlencoded.Rebus
You are not able to post like plain text to web api mvc :SDribble
Using this in your HTTP header Web API should understand that you have an url-encoded body. Could you please share your HTTP Header?Rebus
WebClient client = new WebClient(); client.UploadStringCompleted += client_UploadStringCompleted; client.Headers["Content-Type"] = "application/x-www-form-urlencoded"; client.UploadStringAsync(new Uri(URL), "POST", "ApplicationKey=asdasda&PusherKey=asdasdasd"); to test out your suggestion I have created a new method like public ApiResponse PushMessage(string ApplicationKey, string PusherKey) but it didn't work either because binding has changed in RC. It gives internal server error.Dribble
Ohh i overlooked the fact that you make your request to localhost/Pusher/PushMessage, but WebAPI doesn't use the method name, it identifies the method by http method and params. So try to request localhost/Pusher.Rebus
if you give a special name to a method you may able to use it. This actually works public ApiResponse PushMessage(Request request){ } I could able to make a query.Dribble
I provided a full example (see updated answer). Maybe it can help you.Rebus
What if x and y are properties of the Person class? Can we get these properties FromUri and the other properties FromBody?Unprincipled
You mean send half of the Person in the URI and the other half in the body? I don't know, but I doubt it. Is there any use case for this?Rebus
Why should the content-type be application/x-www-form-urlencoded? I thought that was for requests with url params, and multipart/form-data should be used if there is any non-text body data. That said, I've tried both in this situation and only application/x-www-form-urlencoded works, I would just like to know the explanation.Hooknose
application/x-www-form-urlencoded is for simple data that is sent in the body of the HTTP message and has the form key1=value1&key2=value2. As you correctly said multipart/form-data is for uploading blobs and requires a different format in the HTTP body (Google found this here).Rebus
This didn't work for my WebApi, my problem was that the body was missing prefix "=", see https://mcmap.net/q/121457/-post-string-to-asp-net-web-api-application-returns-nullIsometrics
B
1

The Web API uses naming regulations. The method for a post should be started with Post.

You should rename your PushMessage to method name PostMessage.

Also the web api defaulty listens (depending on your route) to 'api/values/Message' and not to Pusher/Pushmessage.

[HttpPost] attribute is not required

Brittain answered 30/11, 2012 at 10:7 Comment(2)
The method for a post should be started with Post. : Not requiredBlowout
This answer is wrong. The method needs 'Post' in name only when there is no [HttpPost] attribute.Affettuoso
S
0

You may use following code to post json in request body:

var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

Request request = new Request();
HttpResponseMessage response = httpClient.PostAsJsonAsync("http://localhost/Pusher/PushMessage?x=foo&y=bar", request).Result;

//check if (response.IsSuccessStatusCode)
var createResult = response.Content.ReadAsAsync<YourResultObject>().Result;
Syllogize answered 23/8, 2012 at 7:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.