I am making a communication between two microservices. I am trying to obtain the content from the model "UserBookPreference". I already debugged and the content that is being sent in the PostAsync() request is correct (let's say, data from microservice A). The problem arises when I try to receive the contents from the Post method in microservice B. The model type I have as parameter is the same I am sending from the postAsync. Since I am using .NET 5, the JsonContent.Create() method is a good approach according to my reasearch. I have tried other methodologies, such as using the StringContent() method but still I get the null object in microservice B. This is the code I am using.
In microservice A:
public async Task<string> AddFavoriteBook(UserBookPreference bookModel)
{
JsonContent content = JsonContent.Create(bookModel);
var response = await httpClient.PostAsync(URLHelper._baseUserPreferencesMicroserviceURL + "/Book", content);
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
In microservice B:
[HttpPost("Favorites/Book")]
public IActionResult AddUserFavoriteBook(UserBookPreference bookModel)
{
try
{
_prefService.AddUserBookFavorite(bookModel);
return Ok(bookModel);
}
catch (Exception ex)
{
return BadRequest(new { message = ex.Message });
}
}
Thank you for your time.
You need to either add [FromBody] attribute before UserBookPreference in your endpoint or add a [ApiController] attribute to your controller to bind UserBookPreference to incoming body. docks
Related
I'm writing a Blazor web app and once I get the user input using a web form by following https://learn.microsoft.com/en-us/aspnet/core/blazor/forms-validation?view=aspnetcore-5.0#example-form-1. I'm wondering how can I grab all the values from the form covert them to JSON and then send an HTTP post to an endpoint with this JSON payload?
private async Task HandleValidSubmit()
{
var client = _clientFactory.CreateClient();
try
{
starship = await client.PostAsync(uri, HttpContent startship);
}
catch (Exception ex)
{
errorString = "there was an error";
}
}
how to manipulate user input
if you follow the link mentioned in your question you will notice that a startship is a private object and it is referenced in the EditForm as Model Parameter of the component, then the user can change the values of that object.
send the values:
You can use PostAsJsonAsync from System.Net.Http.Json to send the C# object as JSON.
client.PostAsJsonAsync(uri,startship)
I have a HttpGet method in a controller in a windows application project.
I need to return Headers from it, so method's return type is HttpResponsemessage. but not able to get any response from that method.
I have one HttpGet method in a controller in a windows application, it is behaving like a Head method, as I am changing Head request type to HttpGet using Handler (ref).
[HttpGet]
public HttpResponseMessage Get(HttpRequestMessage msg)
{
HttpResponseMessage res = new HttpResponseMessage
{
Content = new StringContent("", Encoding.UTF8, "text/plain")
};
res.Headers.Add("Connection", "Keep-Alive");
res.Headers.Add("Keep-Alive", "timeout = 1000 max = 100");
return res;
//return "Hi";
}
In wireshark when I see request and response,
I don't see any response , also tried by sending request from postman,
I am not able to get any response.
but when I change return type to string in gives status code 200 ok in response.
[HttpGet]
public string Get(HttpRequestMessage msg)
{
return "Hi";
}
But I want to return headers not content.
How can I achieve it?
Can anyone help me on this?
I figure I have to be doing something obviously incorrect in my .NET code but I cannot figure out the issue.
I have two applications talking via RestSharp calls and, no matter what I attempt, the POST value coming from one application to another is ALWAYS NULL. Here is my sending code:
var client = new RestClient(_context.CloudUrl + ":" + _context.CloudPort.ToString() + "/api/web/AddRegisteredLocation");
var request = new RestRequest(Method.POST);
request.RequestFormat = DataFormat.Json;
request.AddHeader("cache-control", "no-cache");
request.AddParameter("application/json", JsonConvert.SerializeObject(myLocation, Formatting.None), ParameterType.RequestBody);
I have tried .AddObject, .AddJsonBody, .AddBody - not using NewtonSoft.Json and even passing XML but this method always receives a NULL value:
[Route("AddRegisteredLocation")]
[HttpPost()]
public async Task<IActionResult> AddRegisteredLocation([FromBody] string NewStringLocation)
{
try
{
RegisteredLocation newLocation = JsonConvert.DeserializeObject<RegisteredLocation>(NewStringLocation);
await _Manager.AddRegisteredLocation(newLocation);
return new OkObjectResult(true);
}
catch (Exception exc)
{
eventWriter.WriteEntry("AddRegisteredLocation failed with the exception: " + exc.ToString(), System.Diagnostics.EventLogEntryType.Error);
return new NotFoundResult();
}
I have also tried this method:
//POST: api/web/AddRegisteredLocation
[Route("AddRegisteredLocation")]
[HttpPost()]
public async Task<IActionResult> AddRegisteredLocation([FromBody] RegisteredLocation NewLocation)
{
try
{
await _Manager.AddRegisteredLocation(NewLocation);
return new OkObjectResult(true);
}
catch (Exception exc)
{
eventWriter.WriteEntry("AddRegisteredLocation failed with the exception: " + exc.ToString(), System.Diagnostics.EventLogEntryType.Error);
return new NotFoundResult();
}
}
And I have dropped the [FromBody] tag - nothing is working. When I walk the code, the incoming value is ALWAYS Null.
If I use a Postman script and send in raw JSON through a POST request, that works fine so it has to be something on the Request side but I cannot figure it out.
Does anybody have a suggestion?
As it turns out, the Bson ObjectId was the culprit - for some reason none of the serializers can handle it. There is a BsonWriter and BsonReader options but both of those essentially use Base64-encoding which is slow and bloats messages.
To quickly overcome the issue, I ended up writing a set of classes without the BsonId and then a bunch of methods that manually copy the data from the MongoDB-based classes to the "serialization-friendly" classes.
This worked perfectly and, on the other end, the lack of an Object ID does not cause any issues with MongoDB. I simply look the object up by a unique string name and assign the ID before making any changes.
This is probably NOT the most elegant solution but it does work!
I have problem understanding sending Json from WebApi to Android. I know how to make requests from Json, but don't know how to make Task that waits for request and return Json. I have json made from Mongo DB query with JsonConvert.SerializeObject.
I have been searching and found this that I have for now, but this isn't what I need I think, I don't have url in PostAsync, I just want to wait for request and respond with Json, where I need to look for:
public async Task<HttpStatusCode> SendAsync()
{
var content = new StringContent(
jsonString,
Encoding.UTF8,
"application/x-www-form-urlencoded");
HttpResponseMessage response = await _httpClient.PostAsync(_url, content);
return response.StatusCode;
}
You need to return an IHttpActionResult implementation. For example:
public async Task<IHttpActionResult> SendAsync()
{
// Object passed to Ok will be automatically serialized to JSON
// if response content type is JSON (and, by default, this is the serialization
// format in ASP.NET WebAPI)
return Ok(new { text = "hello world" });
}
I would like to return a json errormessage but at the moment in fiddler I cannot see this in the json panel:
string error = "An error just happened";
JsonResult jsonResult = new JsonResult
{
Data = error,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
response = Request.CreateResponse(HttpStatusCode.BadRequest, jsonResult.Data);
how to do this?
A few points:
If all you're looking to do is return an error response containing a simple error message, Web API provides a CreateErrorResponse method for that. So you can simply do:
return Request.CreateErrorResponse(HttpStatusCode.BadRequest,
"An error just happened");
This will result in the following HTTP response (other headers omitted for brevity):
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Content-Length: 36
{"Message":"An error just happened"}
If you want to return a custom object instead, then you use Request.CreateResponse like you were doing, but don't use the MVC JsonResult. Instead, just pass your object directly to CreateResponse:
var myError = new
{
Data = "An error just happened",
OtherDetails = "foo bar baz"
};
return Request.CreateResponse(HttpStatusCode.BadRequest, myError);
Now, say you are doing this but you're not getting JSON back from the server. It is important to realize that Web API normally uses content type negotiation to determine what format to use when sending the response back. That means, it looks at the Accept header that was sent by the client with the request. If the Accept header contains application/xml, for example, then Web API will return XML. If the header contains application/json then it will return JSON. So, you should check that your client is sending the correct Accept header.
That said, there are ways to force Web API to always return data in a specific format if that is what you really want. You can do this at the method level by using a different overload of CreateResponse which also specifies the content type:
return Request.CreateResponse(HttpStatusCode.BadRequest, myError,
new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"));
Alternatively, you can remove the XML formatter from the configuration altogether in your WebApiConfig file:
config.Formatters.Remove(config.Formatters.XmlFormatter);
This will force Web API to always use JSON regardless of what the client asks for.
you can return JSON like below,
return Request.CreateResponse<ResponseApiModel>(HttpStatusCode.BadRequest, response);
I recommend to use IHttpActionResult on your method return type instead HttpResponseMessage, if your api's method return type is IHttpActionResult. you can return like;
return Content(HttpStatusCode.InternalServerError, response);
you can check also that link about best practice of error returning Especially #Daniel Little's answer is really useful.
I know the answer added to late but maybe stand someone in good stead.
JsonResult is a MVC concept. It does not work in Web API. One way to explicitly return json content is to use the class I created in this answer https://stackoverflow.com/a/20504951/6819
Add
config.Formatters.Remove(config.Formatters.XmlFormatter);
line in your WebApiConfig file
I think this will help you or others.
define your custom ApiController
public abstract class ApiController : System.Web.Http.ApiController
{
protected internal virtual BadRequestErrorMessageResult BadRequest(object message)
{
return new BadRequestErrorMessageResult(message);
}
}
define custom message result class
public class BadRequestErrorMessageResult : IHttpActionResult
{
private readonly object _message;
public BadRequestErrorMessageResult(object message)
{
_message = message;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new ObjectContent<object>(_message, new JsonMediaTypeFormatter(), "application/json")
};
return Task.FromResult(response);
}
}
use your custom response method
// GET api/<controller>
[Authorize]
[HttpGet]
public IHttpActionResult Test()
{
return BadRequest(new
{
Succeeded = false,
Message = "An error occurred during processing, please contact the administrator!"
});
}
response data with custom header error status code
{"Succeeded":false,"Message":"An error occurred during processing, please contact the administrator!"}
You can directly set the status code of the current HTTP response through Response property
Response.StatusCod = (int)HttpStatusCode.BadRequest;
return Json(HttpStatusCode.BadRequest);