I have a asp.net web API application hosted using OWIN. The web API application uses an external library which depends on System.Web and writes its response on System.Web.Response object. I have set a dummy object to HttpContext.Current and after that the I expect the external library would set the response at HttpRequest. Then I need to know how I could transfer the result from HttpRequest to HttpRequestMessage so that the web API method could process the result.
Here is some sample code:
public HttpResponseMessage GetTest()
{
HttpResponseMessage responseMessage = new HttpResponseMessage();
HttpResponse httpResponse = new HttpResponse(new StreamWriter(new MemoryStream()));
httpResponse.Write("From HttpResponse");
return responseMessage;
}
I have written some text using the HttpResponse.Write() method, now I need to move the result from HttpResponse to HttpResponseMessage.
I believe what you are looking for is IHttpActionResult see link:
https://learn.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with-aspnet-web-api/action-results
Here is an example of how to create a HttpResponseMessage:
public IHttpActionResult Get()
{
HttpResponseMessage responseMessage = "From HttpResponse";
return new ResponseMessageResult(responseMessage);
}
Try:
return Request.CreateResponse(HttpStatusCode.OK, "{data to return here}")
You can try like below:
if (yourCondition)
{
return Request.CreateResponse<Employee>(HttpStatusCode.OK, obj);
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Not Found");
}
Related
I have the following WebClient code that is supposed my code acts as a proxy, and link to remote server, I would like to throw up whatever response that is returned from the remote server, how can I do so? I do not want to handle exceptions or anything, just merely throwing responses.
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "application/json";
Uri NODE_LOGIN_PATH = new Uri(URI_Combine(NodeAPI, "auth/login"));
string jsonString = JsonConvert.SerializeObject(login_details);
JObject data = JObject.Parse(await client.UploadStringTaskAsync(NODE_LOGIN_PATH, jsonString));
return data;
}
You appear to be using WebClient in an MVC 4 project, so you're on old stuff. Consider upgrading to HttpClient and ASP.NET Core.
The principle that you want goes something like this:
public class FooController : ApiController
{
public HttpResponseMessage Get()
{
// Do the HTTP call
var httpResponse = client.DoSomeRequest();
// Translate
var apiResponse = new HttpResponseMessage
{
StatusCode = httpResponse.StatusCode.Map(...),
Headers = httpResponse.Headers.Map(...),
Body = httpResponse.Body.Map(...),
};
// Return
return apiResponse;
}
}
So: do the request, and translate (map) it to the HttpResponseMessage (or IHttpActionResult, or ...) that your Web API platform requires.
I am building a Rest API and a Rest Client, the api url is https://localhost:44341 and the client url is https://localhost:44305/, specifically I want to be able to edit pages in the client for a small custom cms.
Anyway, to view a page in the client, I do this:
public async Task<IActionResult> Edit(long id)
{
Page page = new Page();
using (var httpClient = new HttpClient())
{
using var response = await httpClient.GetAsync("https://localhost:44341/api/Pages/" + id);
string apiResponse = await response.Content.ReadAsStringAsync();
page = JsonConvert.DeserializeObject<Page>(apiResponse);
}
return View(page);
}
And it works, I get the actual page data from the API, however the PUT method in the client is not working, this is it:
[HttpPost]
public async Task<IActionResult> Edit(Page page)
{
using (var httpClient = new HttpClient())
{
using var response = await httpClient.PutAsync("https://localhost:44341/api/Pages/" +
page.Id, new StringContent(page.ToString()));
string apiResponse = await response.Content.ReadAsStringAsync();
}
return Redirect(Request.Headers["Referer"].ToString());
}
When I submit the form for the above method it just redirects to the previous request but the changes aren't saved.
Here's the put method from the api:
[HttpPut("{id}")]
public async Task<ActionResult> PutPage(long id, Page page)
{
if (id != page.Id)
{
return BadRequest();
}
context.Entry(page).State = EntityState.Modified;
await context.SaveChangesAsync();
return NoContent();
}
When I inspect using breakpoints, I can see that the response in the POST method says 415 unsupported media type
The 415 unsupported media type status code means that
The server is refusing to service the request because the entity of
the request is in a format not supported by the requested resource for
the requested method.
When you use new StringContent(page.ToString()) then the media type for the StringContent created defaults to text/plain.
You need to send content in json format:
var content = new StringContent(JsonConvert.SerializeObject(page, Encoding.UTF8, "application/json");
using var response = await httpClient.PutAsync($"https://localhost:44341/api/Pages/{page.Id}", content);
I am posting to an API using HttpClient and getting back the HttpResponseMessage.
I am reading the status code from the reply but I it's always 200
Posting:
var json = JsonConvert.SerializeObject(loginDto);
var stringContent = new StringContent(json, Encoding.UTF8, "application/json");
var client = new HttpClient();
var response = await client.PostAsync("http://localhost:57770/api/Account/Login", stringContent);
I am replying from API the HttpResponseMessage:
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
But when I read the response, it's always 200
How can I achieve this?
Asp.Net Core no longer recognizes HttpResponseMessage as part of the pipeline. This means it will be treated like any other returned model and serialized as content. Hence the 200 OK status.
The API controller action should return IActionResult derived result.
[HttpPost]
public IActionResult SomeAction(...) {
//...
return StatusCode((int)HttpStatusCode.Unauthorized); //401
//...
}
Or just use
return Unauthorized();
which is derived from StatusCodeResult and is used a short hand to replace the code shown above.
Reference ControllerBase.Unauthorized.
I'm building an webapi in c# to be called by an outside server.
let's say my API address is www.server.com/webapi/service1
when I set the address above in the app that will use it, it sends a simple POST with an empty body to service1 and waits for a specific KEY as response (in body), like an authentication. ok.
the same service1 can be called, using POST too, passing a raw JSON in the body, and I'm using the [FromBody] attribute to get the body and process.
I tried this to manage the empty POST call and the call with body data:
[HttpPost]
[Route("webapi/service1")]
public HttpResponseMessage Post()
{
var resp = new HttpResponseMessage(HttpStatusCode.OK);
resp.Content = new StringContent(TokenKey.ToString(), System.Text.Encoding.UTF8, "text/html");
return resp;
}
[HttpPost]
[Route("webapi/service1")]
public async Task<HttpResponseMessage> Post([FromBody] RetornoChat retornoChat)
{
await closedChat(retornoChat); //process body
return resp;
}
but it was not working.I manage a workaround like the code below, I check if the class in [FromBody] is empty, if this is the case return the special string to validate and finish, if there is a body then get the data validate and process. I'm wondering if there is a better solution.
I really thought that the solution was to double the post method and when there was a body it would call the post with the [frombody] and when there is no body it would go to the empty post.
[HttpPost]
[Route("webapi/service1")]
public async Task<HttpResponseMessage> Post([FromBody] RetornoChat retornoChat)
{
var resp = new HttpResponseMessage(HttpStatusCode.OK);
resp.Content = new StringContent(TokenKey.ToString(), System.Text.Encoding.UTF8, "text/html");
if (retornoChat == null)
{
}
else
{
//get the body data and process
}
return resp;
}
Thanks in advance for your time!
I have a Portable Class Library (PCL) method like this:
public async Task<string> GetLineStatuses()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync())
{
return response.GetResponseStream().ReadAllText();
}
}
My ASP.NET Web Api method looks like this:
public async Task<HttpResponseMessage> Get()
{
HttpResponseMessage response = new HttpResponseMessage();
string statuses = await service.GetStatuses();
response.Content = new StringContent(statuses);
return response;
}
What are the implications of returning a Task in Web API. Is this allowed? The only reason I want to use await is so I can use a Portable Class Library (PCL). What is the best practice? Should I have a syncronous version of my method and an asyncronous version? What are the performance and code readability and maintainability implications?
Also would I have the same effect if I returned Task<string> rather than Task<HttpResponseMessage>?
Async and await are perfectly acceptable in ASP.NET. Here's a Scott Handselman video demoing it: http://www.asp.net/vnext/overview/aspnet/async-and-await
"Also would I have the same effect if I returned Task<string> rather than Task<HttpResponseMessage>?"
Not really sure what you mean by this. The Task is like a container for the object, so a Task<string> would contain your string result and a Task<HttpResponseMessage> would contain your HttpResponseMessage result... Is that what you mean? I think either method is perfectly acceptable. If you just need the string, then go with that. No point in returning more than you need.
as alternative:
public static async Task<string> CallGET(string requestUri, string id = "")
{
string responseData;
using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Uri.TryCreate(new Uri(baseURI), $"{requestUri}{(string.IsNullOrEmpty(id) ? string.Empty : $"/{id}")}", out Uri fullRequestUri);
using (var response = await client.GetAsync(fullRequestUri))
{
responseData = await response.Content.ReadAsStringAsync();
}
return responseData;
}
}
and call would be:
var getListUsersResult = Utils.CallGET($"/v1/users").Result;
var resultset= JsonConvert.DeserializeObject(getListUsersResult, typeof(List<UsersDTO>)) as List<UsersDTO>;
UserDTO r = users.Where(d => d.Name.ToLower().Contains("test")).FirstOrDefault();
and another call for one item:
var getUser = Utils.CallGET($"/v1/users", $"{USER_ID}").Result;
var getUserResponse = JsonConvert.DeserializeObject(getUser, typeof(UserDTO)) as UserDTO;