Values of BsonDocument missing when PutAsync over web request? - c#

I am trying to send a simple BsonDocument to WebAPI through PutAsync request.
However, the values of the BsonDocument missing when passed to the WebAPI Controller.
Here are the codes of my client.
public static async Task<HttpResponseMessage> sendBdoc()
{
try
{
var abc = new BsonDocument("Abc","hoho");
var bformatter = new BsonMediaTypeFormatter();
var id = ObjectId.GenerateNewId();
HttpClient client = new HttpClient()
client.BaseAddress = new Uri("http://localhost:58836");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/bson"));
var response = await client.PutAsync($"api/query/{id}", abc, bformatter);
return response;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
Here are the codes of my controller:
public async Task<IHttpActionResult> Put(string id, BsonDocument doc)
{
try
{
//MongoDB Connection stuff here
var filter = new BsonDocument("_id", ObjectId.Parse(id));
var update = collection.ReplaceOneAsync(filter, doc, new UpdateOptions() { IsUpsert = true });
var result = await update;
if (result.IsAcknowledged)
{
return Ok();
}
return NotFound();
}
catch (Exception e)
{
return InternalServerError();
}
}
Screenshot of debugging my client app, variable abc is filled with value.
https://i.stack.imgur.com/txp8l.png
Screenshot of debugging at web controller side, value of the BsonDocument turned null now.
https://i.stack.imgur.com/lBTe3.png
Do i overlook something? Thanks alot

It could be a limitation of the default model binder.
Could you try to remove the "string id" from the Put method and resend the request?

Related

third party API returns httpresponsemessage. can someone help me to understand how to extract data out of httpresponsemessage and return generic type

public async Task<>GetLandProperty(string num)
{
var request = new HttpRequestMessage(HttpMethod.Get, _httpClient.BaseAddress+relativeurl);
// added required headers here.
var response = await _httpClient.SendAsync(request);
}
now here response is httpresponsemessage. i dont understand how to extract data out of response and deserialize it. probably i can create class, fetch response's content and deserialise it but what to do if it return failure response or exception. how to return generic type in this case
This is related to your api code. You can catch the exception information and return different information by setting the HttpStatusCode of HttpResponseMessage in the api side.
In the GetLandProperty method, you can set the return type to object to return different content.
Determine the returned content by judging the status of IsSuccessStatusCode of response. If the status is true, use the type returned by deserialize and return the corresponding object. If it is false, return the response directly.
public async Task<object> GetLandProperty()
{
Product product = null;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("url");
var request = new HttpRequestMessage(HttpMethod.Get, client.BaseAddress);
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
string responseString = response.Content.ReadAsStringAsync().Result;
Newtonsoft.Json.Linq.JObject json = Newtonsoft.Json.Linq.JObject.Parse(responseString);
product = Newtonsoft.Json.JsonConvert.DeserializeObject<Product>(responseString);
return product;
}
return response;
}
}
My api code:
[HttpGet]
public HttpResponseMessage Get(int id)
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
Product persona = _context.Product.FirstOrDefault(p => p.DataID == id);
if (persona != null)
{
response.Content = new StringContent(JsonConvert.SerializeObject(persona));
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
return response;
}
else
{
response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
response.Content = new StringContent("error message");
return response;
}
}
Update
Another method to receive GetLandProperty method returned content:
public async Task<object> CallTest()
{
var obj = await GetLandProperty();
if(obj is Product)
{
Product product= (Product)obj;
// save data to db
}
else
{
//do other operations
return obj;
}
}
Here is the test result by postman:
I am not very sure whats the question.
To get response data
var result = await response.Content.ReadAsStringAsync();
and to desriazile it
var json= JsonConvert.DeserializeObject<T>(result);

500 Error when calling an API in C# with having ID in URL

I need to Call a API using C# to this URL: I changed the URL so not working here but it is working in postman)
https://uattest.com/api/leads/28/comments
This is the object to post:
{
"code":"22535345454-263663",
"text":"This is a test"
}
This is working fine when I post via postman, but when I post using my C# code I am getting 500 error. This is my C# code:
Controller:
[HttpPost]
[Route("AddNote")]
public Task<NoteReturnModel> AddNote(int LeadId, Comments note)
{
return Repository.AddNote(LeadId, note);
}
Repository
public async Task<NoteReturnModel> AddNote(int LeadId, Comments note)
{
using (GetWSObject<NoteReturnModel> addObjectInt = new GetWSObject<NoteReturnModel>())
{
string URL = string.Format("/api/leads/" + LeadId+ "/comments");
return await addObjectInt.PostWSObjectModel(URL, note);
}
}
and this is PostWSObjectModel Method:
public async Task<T> PostWSObjectModel(string uriActionString, Object model)
{
T returnValue = default(T);
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(WebConfigurationManager.AppSettings["URL"]);
var content = new StringContent(JsonConvert.SerializeObject(model));
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = await client.PostAsync(uriActionString, content);
response.EnsureSuccessStatusCode();
returnValue = JsonConvert.DeserializeObject<T>(((HttpResponseMessage)response).Content.ReadAsStringAsync().Result);
}
return returnValue;
}
catch (Exception e)
{
throw (e);
}
}
I am checking all the URLs are correct, in this line that calling HttpResponseMessage response = await client.PostAsync(uriActionString, content); giving error.

Strange response from Asp.Net Web Api Post

I have a Asp.Net Web Api like the following
public async Task<IHttpActionResult> Post(Guid id, OrganisationModel model)
{
try
{
_orgService.AddNewOrganisationToParent(newOrg, org);
await Context.SaveChangesAsync();
return Ok(newOrg.Id);
}
catch (Exception ex)
{
Log.ErrorFormat("Problem creating new organisation {0}. Error {1}", UserId, ex);
return InternalServerError(ex);
}
}
When I call this from another Asp.Net Web application with the following;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var newOrg = Newtonsoft.Json.JsonConvert.SerializeObject(new
{
name = systemTree.Name,
type = 0
});
var content = new StringContent(newOrg.ToString(), Encoding.UTF8, "application/json");
var newOrgId = Guid.Empty;
using (var response = await client.PostAsJsonAsync(orgEndpoint + orgId, content))
{
response.EnsureSuccessStatusCode();
newOrgId = response.Content.ReadAsAsync<Guid>().Result;
}
The response is rather strange, the code shown throws and exception "exceptionMessage": "Unable to translate bytes [B4] at index 3 from specified code page to Unicode.",
If I read this as a string I get the following
"SJN4OMN4��MIK2�M574Ե0H6�500H1NL2J�4IR\u0002\0"
Is there something I am missing? Thanks in advance.

Xamarin.Forms HTTP Post to Web Service - 404 Error

Sorry if this question has been asked already but I can not seem to find one that relates to my issue. I have a web service built using C# Asp.Net Web API, here I have the following POST method:
[HttpPost]
[Route("AddLocation")]
public void PostLocation(Locations model)
{
using (Entities db = new Entities())
{
C_btblFALocation newLocation = new C_btblFALocation()
{
cLocationCode = model.Code,
cLocationDesc = model.Description
};
db.C_btblFALocation.Add(newLocation);
db.SaveChanges();
}
}
In my Xamarin.Forms project I have my Rest Service Class:
public async Task SaveLocationAsync(Locations item)
{
var uri = new Uri(string.Format(Constants.LocationSaveRestUrl));
try
{
var json = JsonConvert.SerializeObject(item);
var content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = null;
response = await client.PostAsync(uri, content);
if (response.IsSuccessStatusCode)
{
Debug.WriteLine(#" Location successfully added.");
}
else
{
Debug.WriteLine(#" Oops, there seems to be a problem.");
}
}
catch (Exception ex)
{
Debug.WriteLine(#" ERROR {0}", ex.Message);
}
}
And my URL is set in my Constants class:
public static string LocationSaveRestUrl = "http://172.16.124.18/ArceusService/api/Assets/AddLocation/";
The problem is I keep getting a 404 error. I have tried every way I can think of to set the URL but no luck. The data seems to be passed through fine from debugging but I don't know how the URL should be for a POST method?
Thanks for any help!
How is your client variable declared? Usually you set a BaseAddress and in your Get/PostAsync you only set the actual resource URI.
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://something.com/api/");
var response = await client.GetAsync("resource/7");
}

Unit testing HttpResponseMessage with Autofac and Moq

I'm going round in circles. So my WebApi returns the output it needs to the browser when i am running in debug. Firefox and IE display the List i need. However when i am trying to unit test the response using Mock and Autofac the HttpResponseMessage I am getting back has no Contents. I get the feeling it is returning on a different context or something like that. I am not totally sure, hence asking the question. I have stringed the below unit test together via googling and the Autofac documentation.
WebApiMethod (contained within InScrapController, _WebScrapSprocService is injected by Autofac in the constructor)
public HttpResponseMessage GetFormItemsByFormNumber(int FormNumber)
{
HttpResponseMessage response;
try
{
//response = Request.CreateResponse(HttpStatusCode.OK, _WebScrapSprocService.GetFormItemsByFormNumber(FormNumber),new MediaTypeHeaderValue("application/json"));
response = Request.CreateResponse(HttpStatusCode.OK, new MediaTypeHeaderValue("application/json"));
response.Content = new StringContent(JsonConvert.SerializeObject(_WebScrapSprocService.GetFormItemsByFormNumber(FormNumber)),Encoding.UTF8, "application/json");
} catch (Exception e)
{
response = Request.CreateResponse(HttpStatusCode.InternalServerError, new StringContent(e.Message), new MediaTypeHeaderValue("application/json"));
}
//Checking if bob knows anything about this...
string bob = response.Content.ReadAsStringAsync().Result;
return response;
}
Unit Test
public void GetFormItemsByFormNumber()
{
using (var mock = AutoMock.GetLoose())
{
var Service = mock.Mock<IWebScrapSprocService>().Setup(x => x.GetFormItemsByFormNumber(3392));
var service = mock.Create<InScrapController>();
service.Request = new HttpRequestMessage();
service.Request.SetConfiguration(new HttpConfiguration());
var HttpResponse = service.Request.CreateResponse(HttpStatusCode.OK, Service, new MediaTypeHeaderValue("application/json"));
var response = service.GetFormItemsByFormNumber(3392);
mock.Mock<IWebScrapSprocService>().Verify(x => x.GetFormItemsByFormNumber(3392));
Assert.AreEqual(HttpResponse, response);
}
}
Those responses are not going to be the same. Also that method under test should be refactored. You are also not getting back any content because you have not setup the service to return anything.
public IHttpActionResult GetFormItemsByFormNumber(int FormNumber) {
IHttpActionResult response;
try {
var result = _WebScrapSprocService.GetFormItemsByFormNumber(FormNumber);
response = Ok(result);
} catch (Exception e) {
response = InternalServerError(e);
}
return response;
}
Next update the test
public void GetFormItemsByFormNumber() {
using (var mock = AutoMock.GetLoose()) {
// Arrange.
var formNumber = 3392;
var items = new List<FormItemsByFormNumber> {
new FormItemsByFormNumber {
//Populate as needed
},
new FormItemsByFormNumber {
//Populate as needed
},
//...etc
};
var serviceMock = mock.Mock<IWebScrapSprocService>();
serviceMock.Setup(x => x.GetFormItemsByFormNumber(formNumber)) // Calling this...
.Returns(items) // should return some value...
.Verifiable(); // and I want to verify that it was called.
var sut = mock.Create<InScrapController>();
// Act.
var response = sut.GetFormItemsByFormNumber(formNumber) as OkNegotiatedContentResult<List<FormItemsByFormNumber>>();
// Assert.
serviceMock.Verify(); //verify setups were exercised as expected.
Assert.IsNotNull(response);
}
}

Categories

Resources