Abdallah
Abdallah

Reputation: 543

Use C# HttpWebRequest to send json data to web service

I am trying to send http request of json data to a web service. It successfully get directed to the web service but the data is always null...

Here is my web service:

public bool CheckUserExist ([FromBody] string Email)
    {
        List<User> all_users = repo.getUsers();
        var match = all_users.Find(i => i.Email == Email);
        if (match == null)
        {
            return false;
        }
        else
        {
            return true;
        }
    }

and here is my Http Request:

var webAddr = "http://localhost:59305/api/User/CheckUserExist";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(webAddr);
httpWebRequest.ContentType = "application/json; charset=utf-8";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
                {
                    string json = "{\"Email\":\"Email\"}";
                    streamWriter.Write(json);
                    streamWriter.Flush();
                }
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                {
                    var result = streamReader.ReadToEnd();
                    return RedirectToAction("Index");
                }

as i mentioned...Iam using a debugger at the web service function...the request get directed to the service but variable "Email" is always null

Upvotes: 3

Views: 7243

Answers (2)

Jason W
Jason W

Reputation: 13209

The quick fix is to change what you are posting. If you want your API endpoint to work with [FromBody] string Email, then you should change your "json":

string json = "\"[email protected]\"";
streamWriter.Write(json);
streamWriter.Flush();

However, you may want to consider a few other changes for the long term on your approach:

  • Let your repo return IQueryable instead of List or some other IEnumerable. As written, you will always return every user from the database. With Linq, you can leverage the lazy initialization and let your query only get the matching user instead of get EVERY user and then find the match. This will not scale well.
  • Use new HttpClient and async functionality in your action instead of HttpWebRequest
  • Instead of manually building your JSON, let .NET do the work and create a class that gets serialized

With the above solutions in place (except for first since you didn't post your data context, didn't want to make too many assumptions), here are some examples to get you started:

Define a shared user search class (shared either in same project or shared DLL)

public class UserSearch
{
    public string Email { get; set; }
}

Let Web API map post against the search class

public bool CheckUserExist([FromBody] UserSearch userSearch)
{
    IQueryable<User> all_users = repo.getUsers();
    var isMatch = all_users.Any(i => i.Email == userSearch.Email);
    return isMatch;
}

Change to HttpClient and use async to send API request with new search class

public async Task<ActionResult> Check()
{
    using (var client = new HttpClient())
    {
        var search = new UserSearch() { Email = "[email protected]" };
        var response = await client.PostAsJsonAsync("http://localhost:59305/api/User/CheckUserExist", search);
        if (response.IsSuccessStatusCode)
        {
            bool exists = await response.Content.ReadAsAsync<bool>();
            // Handle what to do with exists
            return RedirectToAction("Index");
        }
        else
        {
            // Handle unsuccessful call
            throw new Exception("Application error");
        }

    }
}

Upvotes: 4

Carey Tzou
Carey Tzou

Reputation: 77

You can't use string to accept the post data, please define a struct class or use dynamic to receive the Json string.

Upvotes: 1

Related Questions