How to pass model object to Web API Post method - c#

I want to save data to database in MVC application. I have below class which calls the webapi1 service post method. Here Sample is a model object. I have a view which uses the Sample object. I want to inert the Sample Object data to db using the service call.
public SampleTestCreate(Sample)
{
string uri = baseUri + "Test";
using (HttpClient httpClient = new HttpClient())
{
Task<HttpResponseMessage> response = httpClient.PostAsJsonAsync(uri, new StringContent(JsonConvert.SerializeObject(Test)));
// Task<HttpResponseMessage> response = httpClient.PostAsJsonAsync(uri, Test);
var data = response.Result.Content.ReadAsStringAsync().Result;
return JsonConvert.DeserializeObjectAsync<Test>(response.Result.Content.ReadAsStringAsync().Result).Result;
}
}
// POST api/Sample
public HttpResponseMessage PostSample(Sample Sample)
{
if (ModelState.IsValid)
{
db.Samples.Add(Sample);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, Sample);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = Sample.SampleID }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
Here my service post method is getting called , but the "Sample" objects all the properties values are coming null. The model object binding is not happening.

Related

How to store object data from an asynchronous task?

I have a controller method that gets a data from an API.
The LeaveBalanceAsync is called by an AJAX when my page loads.
public async Task<IActionResult> LeaveBalanceAsync(int empnum)
{
return await APICallAsync(empnum);
}
private async Task<IActionResult> APICallAsync(int emp)
{
//Fetch the JSON string from URL.
LeaveModel leave = new LeaveModel();
string apiUrl = $"http://myapi/{emp}";
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(apiUrl);
if (response.IsSuccessStatusCode)
{
APIResponse<LeaveModel> apiResponse = JsonConvert.DeserializeObject<APIResponse<LeaveModel>>(await response.Content.ReadAsStringAsync());
leave = apiResponse.Data;
userLeave = leave;
}
//Return the Deserialized JSON object.
return Json(leave);
}
I would like to store the data that I got from that method to an object like this (as you can see above I tried to pass it into the userLeave model/object but after the LeaveBalanceAsync is done executing,the data that was captured and stored into userLeave is also gone)
public LeaveModel userLeave = new LeaveModel();
Or is there any possible ways I can do this using another method to store it into that object?

Serialize async response from a database client

I have an endpoint which is used to create an item. The controller calls the service which creates the item, makes some changes on the db and db returns data based on the procedure. The db returns a json like response, but is not always the same, so I have to adjust on the backend so that I can formalize the response type.
The problem is that create item service is asynchronous and I need to be able to await the response so I can make a new response based on that. How can I await the response and that I get from db client and then return data based on that.
This is my Action and I want to be able to serialize async response from service
[HttpPost]
public IActionResult CreateItem([FromBody] InputModel item)
{
var jsonString = _itemService.CreateItem(item);
ResponseModel? response = JsonSerializer.Deserialize<ResponseModel>(jsonString);
return new ObjectResult(response.Response) { StatusCode = response.StatusCode };
}
The default response model
public class ResponseModel
{
public string Response { get; set; }
public int StatusCode { get; set; }
}
Create Item service, which makes the post request to the client and it has to be async.
Depending on the status code that is coming from the client, I want to be able to set my action status code as well.
public async Task<string> CreateItem(InputModel item)
{
if (item.VersionType != 1)
{
return new { Response = "Incorrect data", StatusCode = 400 }.ToString()!;
}
var json = JsonSerializer.Serialize(item);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, data);
var content = await response.Content.ReadAsStringAsync();
return content;
}
You can make your action method async and then await the method call _itemService.CreateItem for it :
[HttpPost]
public async Task<IActionResult> CreateItem([FromBody] InputModel item)
{
var jsonString = await _itemService.CreateItem(item);
ResponseModel? response = JsonSerializer.Deserialize<ResponseModel>(jsonString);
return new ObjectResult(response.Response) { StatusCode = response.StatusCode };
}
Now your action method would asyncrounously wait for the result from CreateItem and when it returs result, it will continue executing further and send the deserialized response back to client.

Send Http Request from Blazor Component

I'm using .Net Core 3.1 and I'm having trouble sending requests from a Blazor component. I want to send a request to a controller I have, and these requests systematically end up in 400 Bad request.
In my Startup.cs, I have
if (!services.Any(x => x.ServiceType == typeof(HttpClient)))
{
services.AddScoped<HttpClient>(s =>
{
var uriHelper = s.GetRequiredService<NavigationManager>();
return new HttpClient
{
BaseAddress = new Uri(uriHelper.BaseUri)
};
});
}
In my Blazor component, I have:
var json2 = Newtonsoft.Json.JsonConvert.SerializeObject(_Model);
var stringContent2 = new StringContent(json2, System.Text.Encoding.UTF8, "application/json");
var response2 = await Http.PostAsync("/[controllerName]/[Method]", stringContent2);
if (response2.IsSuccessStatusCode)
{
var resultContent = response2.Content.ReadAsStringAsync().Result;
return resultContent;
}
else
return "failed";
And here is my Controller Method prototype:
[HttpPost]
public IActionResult Method([FromBody] Model form)
{...}
Would you happen to see what's wrong with the code?
You are passing a StringContent object in your PostAsync method, but in your action you have your Model as a parameter.
You have two options :
To change your action parameter to a StringContent.
To parse the Json as your Model to pass it to the PostAsync method content parameter.
Regards,
these requests systematically end up in 400 Bad request.
Please check you provide correct request header(s) and well-formatted data while you make request from your Blazor app to backend service.
I did a test using following code snippet with simple testing data, which work well on my side. If possible, you can create a new component and test if the code snippet can work for you.
var _Model = new Model { Id = 1, Name = "fehan" };
var json2 = Newtonsoft.Json.JsonConvert.SerializeObject(_Model);
var stringContent2 = new StringContent(json2, System.Text.Encoding.UTF8, "application/json");
var response2 = await Http.PostAsync("Home/Method", stringContent2);
if (response2.IsSuccessStatusCode)
{
var resultContent = response2.Content.ReadAsStringAsync().Result;
}
Model class
public class Model
{
public int Id { get; set; }
public string Name { get; set; }
}
Test Result
Besides, if you are making request to MVC controller action, please check if you enabled antiforgery validation on controller or action(s).

Pass dynamic object to common method for Post data in Application

In my application, it is calling webapi, and application is in MVC5. Now I have many more methods in application project. So I want to create one common(global) method to call the api. Methods which are used for get content those are working fine, but methods, those are used to post(means save data to DB kind of) data, getting error like this. Code is like below:
public static string SendDataToAPI(dynamic objCommon, string urlParameters, ref string errorMessage)
{
try {
string url = ConfigurationSettingHelper._BaseUrl;
string strJson = string.Empty;
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var response = client.PostAsJsonAsync(urlParameters, objCommon);
if (response.Result.IsSuccessStatusCode)
{
strJson = response.Result.Content.ReadAsStringAsync().Result;
}
else {
errorMessage = response.Result.Content.ReadAsStringAsync().Result;
}
return strJson;
}
}
catch (Exception ex) {
errorMessage = ex.Message;
return errorMessage;
}
}
So, my question is how can I pass dynamic object type in PostAsJsonAsync method? How can I set this kind of method for common use?
Try something below where the post data model generically accepts any type and complex object also should be wrapped into single model.
public async virtual Task<string> ExecuteHttpApiCall<TModel>(TModel model, string url)
{
HttpResponseMessage response;
using (var client = new HttpClient())
{
if (model != null)
{
response = await client.PostAsJsonAsync(url, model);
}
else
{
response = await client.GetAsync(url);
}
return await response.Content.ReadAsStringAsync();
}
}

HttpResponseMessage from HttpClient to User Defined Object C#

I have seen similar questions asked but none that seem to help me with my issue so please bear with me.
I have a WebAPI controller method that is defined as such:
[HttpPost]
[Route("")]
public HttpResponseMessage CreateMyObject(MyObjectRequest myObject)
{
MyObject o;
try
{
o = _serviceFactory.GetInstance().CreateMyObject(myObject);
}
catch (Exception ex)
{
ex.WriteToLog();
throw ApiHelper.CreateResponseException(HttpStatusCode.InternalServerError, ex);
}
var response = Request.CreateResponse(HttpStatusCode.Created, o);
var uri = Url.Link("GetMyObjectById", new { myObjectId = o.MyObjectId.ToString() });
response.Headers.Location = new Uri(uri);
return response;
}
Say, MyObject contains two properties,
public MyObject
{
public Guid MyObjectId;
public string MyObjectName
}
A client was written to call these controller methods in a WPF application. Here is the client method that is being used:
public HttpResponseMessage CreateQuote(MyObjectRequest myObject)
{
var hashtable = new Hashtable
{
{"myObject", myObject}
};
var task = GetResponse("", hashtable);
var response = task.Result;
return response;
}
protected async Task<HttpResponseMessage> GetResponse(string path, Hashtable parameters)
{
var response = await GetAsync(BuildRequestUri(path, parameters)).ConfigureAwait(false);
return response.IsSuccessStatusCode ? response : new HttpResponseMessage();
}
protected async Task<HttpResponseMessage> GetResponse(string path)
{
return await GetResponse(path, null);
}
The controller and supporting client code was not written by me and was already in the system. I am just consuming this in the WPF application. Now, I am trying to call the controller method via the client in the application and get the MyObject from the response so that I can access the MyObjectId that has been created and set. I have tried some of the other responses to similar questions but have not even seen some of the methods that are called on the response in order to get the information. Here is the first part of the call to the client that I have in the application:
var httpResponse = ApplicationService.CreateMyObject(myObjectRequest);
The application service simply injects the client into the constructor and allows me to call the CreateMyObject method. Is there any insight that can be given to me on how I should be getting the MyObject object out of the response?
I'm still a little new to web api as well, but I'm currently working with it on a project. Give the following code a try:
MyObject myObject;
if (response.IsSuccessStatusCode)
{
// Parse the response body. Blocking!
myObject = response.Content.ReadAsAsync<MyObject>().Result;
}
So you could theoretically change your method like this (may not be exactly what you want):
public MyObject CreateQuote(MyObjectRequest myObject)
{
var hashtable = new Hashtable
{
{"myObject", myObject}
};
var task = GetResponse("", hashtable);
var response = task.Result;
MyObject newObject;
if (response.IsSuccessStatusCode)
{
// Parse the response body. Blocking!
newObject= response.Content.ReadAsAsync<MyObject>().Result;
}
return newObject; // instead of response
}

Categories

Resources