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?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
kkocabiyik
  • 4,246
  • 7
  • 30
  • 40

3 Answers3

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));
    }
}
Johannes Egger
  • 3,874
  • 27
  • 36
  • 1
    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! – kkocabiyik Aug 22 '12 at 11:56
  • Ensure that the HTTP header contains `Content-Type: application/x-www-form-urlencoded`. – Johannes Egger Aug 22 '12 at 12:12
  • You are not able to post like plain text to web api mvc :S – kkocabiyik Aug 22 '12 at 12:17
  • Using this in your HTTP header Web API should understand that you have an url-encoded body. Could you please share your HTTP Header? – Johannes Egger Aug 22 '12 at 12:20
  • 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. – kkocabiyik Aug 22 '12 at 12:25
  • 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. – Johannes Egger Aug 22 '12 at 12:32
  • 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. – kkocabiyik Aug 22 '12 at 12:34
  • I provided a full example (see updated answer). Maybe it can help you. – Johannes Egger Aug 22 '12 at 13:18
  • What if `x` and `y` are properties of the `Person` class? Can we get these properties `FromUri` and the other properties `FromBody`? – Luke T O'Brien Jun 14 '16 at 16:19
  • 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? – Johannes Egger Jun 14 '16 at 17:22
  • 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. – Alan Thomas Aug 24 '16 at 21:17
  • `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](http://stackoverflow.com/questions/16416601/c-sharp-httpclient-4-5-multipart-form-data-upload) here). – Johannes Egger Aug 25 '16 at 07:25
  • This didn't work for my WebApi, my problem was that the body was missing prefix "=", see https://stackoverflow.com/a/13771631/782022 – aeroson Mar 09 '18 at 15:37
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

j0k
  • 22,600
  • 28
  • 79
  • 90
Gertjan
  • 519
  • 4
  • 5
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;
abatishchev
  • 98,240
  • 88
  • 296
  • 433
napp
  • 3
  • 4