IHttpActionResult WEB API Response Header - asp.net-web-api2

I am using the IHttpActionResult Type for the API Call which is Get call and i want to send the Response Header in a same call above is my code
[HttpGet]
public IHttpActionResult GetSyncData()
{
syncDataRepository.Location = JsonConvert.SerializeObject(SyncDataOfMobileDatatSet.Location);
syncDataRepository.UserLocation = JsonConvert.SerializeObject(SyncDataOfMobileDatatSet.UserLocation);
syncDataRepository.UserAuthentication = JsonConvert.SerializeObject(SyncDataOfMobileDatatSet.UserAuthentication);
syncDataRepository.UserDetails = JsonConvert.SerializeObject(SyncDataOfMobileDatatSet.UserDetails);
syncDataRepository.TourOrganization = JsonConvert.SerializeObject(SyncDataOfMobileDatatSet.TourOrganization);
syncDataRepository.TourBatch = JsonConvert.SerializeObject(SyncDataOfMobileDatatSet.TourBatch);
syncDataRepository.TourSuperBatch = JsonConvert.SerializeObject(SyncDataOfMobileDatatSet.TourSuperBatch);
syncDataRepository.TourPlanItemChat = JsonConvert.SerializeObject(SyncDataOfMobileDatatSet.TourPlanItemChat);
syncDataRepository.TourBatchPlan = JsonConvert.SerializeObject(SyncDataOfMobileDatatSet.TourBatchPlan);
syncDataRepository.MyRole = JsonConvert.SerializeObject(Roles.GetRolesForUser(HttpContext.Current.User.Identity.Name));
syncDataRepository.DeletedBatchPlan = JsonConvert.SerializeObject(SyncDataOfMobileDatatSet.DeletedBatchPlan);
syncDataRepository.Mode = JsonConvert.SerializeObject(SyncDataOfMobileDatatSet.Mode);
string jsonData = JsonConvert.SerializeObject(syncDataRepository);
return Json(syncDataRepository);
}
i tried with HttpContext.Response but i am getting it as null. so is there any other way please help me.
Thank You.

You can set a response header by implementing the IHttpActionResult and setting the header in the ExecuteAsync method like so :
public class DateHeaderActionResult<TContent> : IHttpActionResult
{
private DateTime _date;
private TContent _content;
private HttpRequestMessage _request;
public DateHeaderActionResult(DateTime date, TContent content, HttpRequestMessage request)
{
_date = date;
_content = content;
_request = request;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = _request.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("MyDate", _date.ToString("yyyyMMddThhmmss"));
response.Content = new ObjectContent<TContent>(_content, new JsonMediaTypeFormatter());
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return Task.FromResult(response);
}
}
And then in your controller instead of returning
return Json(syncDataRepository);
You would return
return new DateHeaderActionResult<SyncDataRepository>(DateTime.Now, syncDataRepository, Request);
That's assuming the syncDataRepository class name is SyncDataRepository

Related

Response code: 400 Bad request/Error Message: No Ids were specified

I am trying to send Get request using RestSharp but getting this message in response:Bad Request/
{"Message":"P1001: No Ids were specified"}. Could someone help please to figure out that? Seems like it's not adding Parameter list to the Request Body...
Here is my code:
public partial class DTO
{
public List<string> evidenceIds { get; set; }
}
public RestRequest GetPlayRequest(Method requestType, string token)
{
DTO MyObject = new DTO();
MyObject.evidenceIds = new List<string>();
MyObject.evidenceIds.Add("6F00CAE1-F16E-47F6-AF3F-D10305DD7859");
string jsonString = JsonConvert.SerializeObject(MyObject);
var restRequest = new RestRequest(requestType);
restRequest.RequestFormat = DataFormat.Json;
restRequest.AddParameter("text/json", jsonString, ParameterType.RequestBody);
restRequest.AddHeader("Organization", "Bofa");
restRequest.AddHeader("Username", "Admin");
restRequest.AddParameter("Authorization", "Bearer " + token, ParameterType.HttpHeader);
return restRequest;
}
The request with all params
The Content response after sending the request
I can suggest the following:
public RestRequest GetPlayRequest(Method method, string token)
{
var obj = new DTO { evidenceIds = new string[]
{"6F00CAE1-F16E-47F6-AF3F-D10305DD7859" }
};
return new RestRequest(method)
.AddJsonBody(obj)
.AddHeader("Organization", "Bofa")
.AddHeader("Username", "Admin");
.AddHeader("Authorization", $"Bearer {token}");
}

Content Type Header in Azure Function

How can I return HTTP Content-Type "application/json" header? Can not find a sample in net...
[FunctionName("Function1")]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
Dictionary<string, string> dd = Parser(requestBody);
string json = JsonConvert.SerializeObject(dd);
if (json == null)
{
return new BadRequestObjectResult("Please pass request body");
}
return (ActionResult)new OkObjectResult(json);
}
1 - By specifying it in your request "Accept : application/json". Azure functions will natively return the type requested in the Accept header. Your code should already be correctly honouring that request.
2 - By returning a JsonResult
The following code will ignore the Accept header and return "application/json" in every case - your serialization is redundant.
[FunctionName("Function1")]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
Dictionary<string, string> dd = Parser(requestBody);
if (dd == null) return new BadRequestObjectResult("Please pass request body");
return (ActionResult) new JsonResult(dd);
//return (ActionResult) new OkObjectResult(dd);
}
You could do this by accessing the Response object via the request's HttpContext:
[FunctionName("Function1")]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
Dictionary<string, string> dd = Parser(requestBody);
string json = JsonConvert.SerializeObject(dd);
if (json == null)
{
return new BadRequestObjectResult("Please pass request body");
}
//add this line...
req.HttpContext.Response.Headers.Add("Content-Type", "application/json");
return (ActionResult)new OkObjectResult(json);
}
I believe you are looking for the CreateResponse class:
var jObject = JObject.Parse(resp);
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(jObject.ToString(), Encoding.UTF8, "application/json");
return response;

Is there any in-built function/method to return, IActionResult/ActionResult instead of HttpResponseMessage in .Net Core 3.1

My Action method is returning HttpResponseMessage but, I want to get rid off Microsoft.AspNetCore.Mvc.WebApiCompatShim NuGet Package (which is basically provided to bridge the gap while porting Asp.Net Web API code into .Net Core) and use IActionResult/ActionResult instead of HttpResponseMessage.
My Action method looks like this:
[HttpGet]
[Route("GetTemplate")]
public async Task<HttpResponseMessage> GetTemplate(string id) {
var userAgent = this.Request.Headers.UserAgent;
bool IsWindows = true;
if(userAgent.ToString().ToLower().Contains("apple")) {
IsWindows = false; //false
}
var template = await _templateService.GetTemplateContent(id);
HttpResponseMessage responseMsg = new HttpResponseMessage();
if(IsWindows) {
responseMsg.Content = new StringContent(JsonConvert.SerializeObject(template));
responseMsg.RequestMessage = Request;
responseMsg.StatusCode = HttpStatusCode.OK;
responseMsg.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/json");
} else {
responseMsg.Content = new ByteArrayContent(template.ContentBytes);
responseMsg.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileNameStar = template.Name };
responseMsg.Content.Headers.Add("x-filename", template.Name);
responseMsg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
responseMsg.Content.Headers.ContentLength = template.ContentBytes.Length;
responseMsg.RequestMessage = Request;
responseMsg.StatusCode = HttpStatusCode.OK;
}
return (responseMsg);
}
Since you aren’t doing anything fancy there, you can translate your return object directly into corresponding action results here. In your case, you want a JsonResult and a FileResult with a custom response header:
[HttpGet]
[Route("GetTemplate")]
public async Task<HttpResponseMessage> GetTemplate(string id)
{
var userAgent = this.Request.Headers.UserAgent;
bool IsWindows = !userAgent.ToString().ToLower().Contains("apple");
var template = await _templateService.GetTemplateContent(id);
if (IsWindows)
{
return Json(template);
}
else
{
Response.Headers.Add("x-filename", template.Name);
return File(template.ContentBytes, "application/octet-stream", template.Name);
}
}
There are a lot similar utility methods on the Controller and ControllerBase type that help you create a variety of different response messages. For most use cases, there should be a built-in way to produce the response.
1stly change the signature of your action to this:
public async Task<IActionResult> GetTemplate
You will then return your data in the response something like this return Ok(data). You do not have to serialize your data, you can send a POCO class. This would represent .StatusCode = HttpStatusCode.OK
If you want to add extra headers to your response, you will do so using the Response field from ControllerBase. Eg. Response.Headers.Add for adding key value pairs to your Response header.

Custom batch handler in asp.net webapi

I want to write custom batch handler in my webapi.
Requirement for this : I am not able to identify weather the incoming request is part of batch or independent.
By writing custom batch handler i will be able to add value in header of each request, which i can use later to identify.
First we need to write custom batch hahttps://stackoverflow.blog/2011/07/01/its-ok-to-ask-and-answer-your-own-questions/ndler
For this we need to override HttpMessageHandler. Below is code
public class BatchHandler : HttpMessageHandler
{
HttpMessageInvoker _server;
public BatchHandler(HttpConfiguration config)
{
// BatchServer is a class which overrides
_server = new HttpMessageInvoker(new BatchServer(config));
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
// Return 400 for the wrong MIME type
// As batch request will always be of MIME type
if ("multipart/mixed" !=
request.Content.Headers.ContentType.MediaType)
{
return request.CreateResponse(HttpStatusCode.BadRequest);
}
// Start a multipart response
var outerContent = new MultipartContent("batch");
var outerResp = request.CreateResponse();
outerResp.Content = outerContent;
// Read the multipart request
var multipart = await request.Content.ReadAsMultipartAsync();
foreach (var httpContent in multipart.Contents)
{
HttpResponseMessage innerResp = null;
try
{
// Decode the request object
var innerReq = await
httpContent.ReadAsHttpRequestMessageAsync();
innerReq.Headers.Add("IsBatch", "true");
// Send the request through the pipeline
innerResp = await _server.SendAsync(
innerReq,
cancellationToken
);
}
catch (Exception ex)
{
// If exceptions are thrown, send back generic 400
innerResp = new HttpResponseMessage(
HttpStatusCode.BadRequest
);
}
// Wrap the response in a message content and put it
// into the multipart response
outerContent.Add(new HttpMessageContent(innerResp));
}
return outerResp;
}
}
in above code their is this line
// BatchServer is a class which overrides HttpServer
_server = new HttpMessageInvoker(new BatchServer(config));
if we don't do this we gets an error
The 'DelegatingHandler' list is invalid because the property
'InnerHandler' of 'xxhandler' is not null.\r\nParameter
name: handlers
Below is the BatchServer class which overrides HttpServer
public class BatchServer : HttpServer
{
private readonly HttpConfiguration _config;
public BatchServer(HttpConfiguration configuration)
: base(configuration)
{
_config = configuration;
}
protected override void Initialize()
{
var firstInPipeline = _config.MessageHandlers.FirstOrDefault();
if (firstInPipeline != null && firstInPipeline.InnerHandler != null)
{
InnerHandler = firstInPipeline;
}
else
{
base.Initialize();
}
}
}
Now we want to hit batch request on BatchHandler
For this we need configure route to BatchHandler
Add below code to your AppStart
var batchHandler = new BatchHandler(config);
config.Routes.MapHttpRoute("batch", "api/batch", null, null, batchHandler);

I can't get a POST to work with my ASP.NET Web API 2 server

I am using Web API 2. I have the following in my controller (and more):
[Route("about")]
public string GetAbout()
{
IPrincipal principal = RequestContext.Principal;
IPrincipal user = User;
return string.Format("principal: {0}, user: {1}", principal == null || principal.Identity == null ? null : principal.Identity.Name,
user == null ? null : user.Identity.Name);
}
[Route("license/exchange")]
//public string PostUser([FromBody]string value)
public XmlDocument PostLicenseExchange(XmlDocument xml)
{
Trap.trap();
int x = 3;
return xml;
}
In my browser, If I put in the URI http://localhost:13770/about, I get the data back.
But I I try a POST to http://localhost:13770/license/exchange, I get:
System.Net.WebException occurred
Message=The remote server returned an error: (401) Unauthorized.
Source=System
StackTrace:
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at EnforcedVacationCommon.LicenseServer.ServerComm.GetResponseCallback(IAsyncResult asynchronousResult) in c:\src\EnforcedVacation\EnforcedVacationCommon\LicenseServer\ServerComm.cs:line 137
InnerException:
I am calling using:
Start() {
// start the request
Uri httpSite = new Uri(URI_LICENSE_SERVER);
WebRequest wreq = WebRequest.Create(httpSite);
wreq.Method = "POST";
wreq.ContentType = "text/xml";
RequestState requestState = new RequestState(asyncCallback, xmlDoc.ToString(SaveOptions.DisableFormatting), msgGuid, wreq);
wreq.BeginGetRequestStream(GetRequestStreamCallback, requestState);
}
private static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
RequestState requestState = (RequestState)asynchronousResult.AsyncState;
using (Stream postStream = requestState.Request.EndGetRequestStream(asynchronousResult))
{
byte[] byteArray = Encoding.UTF8.GetBytes(requestState.XmlRequest);
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
}
requestState.Request.BeginGetResponse(GetResponseCallback, requestState);
}
private static void GetResponseCallback(IAsyncResult asynchronousResult)
{
RequestState requestState = (RequestState)asynchronousResult.AsyncState;
// exception on this call
using (HttpWebResponse response = (HttpWebResponse) requestState.Request.EndGetResponse(asynchronousResult))
What am I doing wrong?
You need to specify that this is a Http Post method with an attribute on the action result as such.
[HttpPost]
[Route("license/exchange")]
//public string PostUser([FromBody]string value)
public XmlDocument PostLicenseExchange(XmlDocument xml)
{
Trap.trap();
int x = 3;
return xml;
}
You can see the documentation by clicking here.