ASP.Net Core 1.1 MiddleWare response - asp.net-core-1.1

I am replacing a HttpHandler with a middleware service. I have all the code working except for returning the actual image. All the existing samples are for asp.net Core (or earlier) , but with asp.net core 1.1 the response object has change?
public async Task Invoke(HttpContext context)
{
var mediaType = new MediaTypeHeaderValue("image/jpeg");
mediaType.Encoding = System.Text.Encoding.UTF8;
context.Response.ContentType = mediaType.ToString();
byte[] results = some process that generates a byte array
Stream stream = new MemoryStream(results);
context.Response.Body = stream;
await _next.Invoke(context);
}
So how do we attach the byte array to the response object?

There is couple of methods which you can use on .NET Core 1.1:
httpContext.Response.Body.WriteAsync([BUFFER], [OFFSET], [COUNT]);
httpContext.Response.Body.Write([BUFFER], [OFFSET], [COUNT]);
httpContext.Response.Body.WriteByte([BYTE]);
httpContext.Response.WriteAsync([TEXT])

Related

Reading Request body in .net core 3.1

I am trying to read request body in ActionFilter but having some strange errors.
What I tried so far:
Copying request body to memory stream
context.HttpContext.Request.Body.CopyTo(memoryStream)
Throws an error that only async operations are supported.
Copying request body to memory stream async
context.HttpContext.Request.Body.CopyToAsync(memoryStream).Wait()
Copies 0 bytes
Using BodyReader:
context.HttpContext.Request.BodyReader.AsStream(true).CopyToAsync(requestBody).Wait();
throws ArgumentOutOfRange exception 'Specified argument was out of the range of valid values. (Parameter 'start')'
I am using .net core 3.1
I had to convert my code to MiddleWare which is able to deal with Body stream:
MIddleware ccaptures request and put it to service.
Action filter access service and decides what to do with it.
Here is a code of middleware
public class RequestReaderMiddleWare
{
private readonly RequestDelegate _next;
public RequestReaderMiddleWare(RequestDelegate next)
{
_next = next;
}
public virtual async Task Invoke(HttpContext context)
{
//replace and revert original request stream
var requestBodyStream = new MemoryStream();
var originalRequestBody = context.Request.Body;
await context.Request.Body.CopyToAsync(requestBodyStream);
requestBodyStream.Seek(0, SeekOrigin.Begin);
var bodyContentService = context.RequestServices.GetService(typeof(BodyContentService))
as BodyContentService;
bodyContentService.Body = requestBodyStream.ToArray();
requestBodyStream.Seek(0, SeekOrigin.Begin);
context.Request.Body = requestBodyStream;
await _next(context);
context.Request.Body = originalRequestBody; //restore request body
}
}
PS: You need to register it in startup:
app.UseMiddleware<RequestReaderMiddleWare>();

What is the alternative for HttpContext.Response.OutputStream to use in WebAPI's HttpResponseMessage

I'm writing a WebAPI for handling PDF documents. It was written in a ashx page earlier implementing IHttpHandler and getting the context using HttpContext. I'm now writing it using WebAPI. In WebAPI we have HttpResponseMessage. For HttpContext.Response.BinaryWrite we have new ByteArrayContent in HttpResponseMessage. But what is the alternative for HttpContext.Response.OutputStream in WebAPI? I need to have the alternative of OutputStram in WebAPI because im passing this OutputStream as a parameter to another dll.
Code in ashx:
SomeReport.PdfReport rpt = new SomeReport.PdfReport(docID);
rpt.CreateReport(context.Response.OutputStream);
Actually you can use any stream for example MemoryStream but result should be wrapped into StreamContent.
public HttpResponseMessage Get()
{
var response = Request.CreateResponse();
var outputStream = new MemoryStream();
//write data to output stream
//or passing it to somewhere
outputStream.WriteByte(83);
outputStream.Position = 0;
response.Content = new StreamContent(outputStream);
return response;
}
If you need direct writing to output stream, please consider using PushStreamContent. Example

Web API file transfer unauthorized error

I'm writing a simple Web API application using ASP.NET MVC 5 and Web API v2. The api should receive a binary file from a client that uses HttpClient in a Winforms application. The application and the web site should be running on a closed network with Active Directory.
The controller:
[Route("FileTest"]
public HttpResponseMessage PostTest([FromBody]HttpPostedFileBase file)
{
// does nothing just retuns ok
}
The client:
public void SendFile(string fileName)
{
using(FileStream fileStream = new FileStream(fileName, fileMode.open, FilleAccess.read))
{
using(MultipartFormDataContent data = new MultipartFormDataContent ())
{
using(StreamContent streamcontent = new StreamContent(fileStream))
{
data.Add(streamcontent );
HttpClient client = new HttpClient();
res = client .PostAsync("address", data).Result;
res.EnsureSucessStatusCode(); // exception unauthorized
}
}
}
Why is this not working?
HttpPostedFileBase is a MVC class, it is not a Web API class, so it is unlikely they will work together.
Instead of trying to pass the file as a parameter, just read the request content as a stream.
[Route("FileTest"]
public async Task<HttpResponseMessage> PostTest(HttpRequestMessage request)
{
var stream = await request.Content.ReadAsStreamAsync();
// ...
}

WebApi Output Cache

I'm trying to implement an output cache in WebApi that can cache the responses already processed by filters and generate responses that are not processed by formatters.
From what I've seen ActionFilterAttribute's OnActionExecuting and OnActionExecuted are execute before the serialization formatters and so if you cache a response, at a cache hit you will respond the exact same content and that content will be serialized again to transmission.
As a possible solution in MVC I think that you can do this by implementing a IResultFilter that override OnResultExecuted by caching the serialized response. With this approach I don't know how to intercept the request handling to avoid the serialization formatters, I think that a possible solution to intercept is create a custom ActionResult to be handled directly by IResultFilter. Please note that this solution is not suitable for me because I'm implementing OutputCache in a WebApi application.
While writing the response, formatters in Web API come into action for HttpContents of type ObjectContent only.
In you OnActionExecuted method, you could force the serialization to happen by doing something like below and then set the response content as StreamContent (this way the formatters wouldn't be coming into picture):
An example below:
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
HttpResponseMessage response = actionExecutedContext.Response;
if (response != null && response.IsSuccessStatusCode)
{
ObjectContent originalContent = response.Content as ObjectContent;
if (originalContent != null)
{
MemoryStream ms = new MemoryStream();
// NOTE:
// 1. We are forcing serialization to occur into a buffered stream here
// 2. This can cause exception. You can leave it as it is and Web API's exception handling mechanism should
// do the right thing.
originalContent.CopyToAsync(ms).Wait();
// reset the position
ms.Position = 0;
StreamContent newContent = new StreamContent(ms);
// Copy the headers
foreach (KeyValuePair<string, IEnumerable<string>> header in originalContent.Headers)
{
newContent.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
//dispose the original content
originalContent.Dispose();
//TODO: cache this new httpcontent 'newContent' (so we are caching both serialized body + headers too)
//Set the response
//NOTE: This newContent will not hit the formatters
actionExecutedContext.ActionContext.Response.Content = newContent;
}
}
}

WebService ASP.NET MVC 3 Send and Receive

I've been racking my brain for a couple of days now on how to approach a new requirement.
I have two websites. The first one lets the user fill out an application. The second website is an internal website use to manage the users applications. I need to develop a "web service" that sends the application data from website 1 to website 2 and return a response to website 2 of success or failure. I have never done a web service before and I'm a bit confused on where to start. I've been reading various examples online but they all seem to be just a starting point for building a webservice... no specific examples.
So for posting the data website 1, what would my controller method look like? Do I use Json to post the data to website 2? What would and example of that look like? Is there some form of redirect in the method that points to website 2?
So for posting the response back to website 2 what would that controller method look like? I assume I would use Json again to send the response back to website 1? Is there some form of redirect in the method that points back to website 1?
I would use JSON and POST the application to the web service.
First I am assuming the application data is contained in some type of object. Use JSON.Net to serialize the object into JSON. It will look something like the following code.
var application = new Application();
string serializedApplication = JsonConvert.Serialize(application);
Second is to POST the code your endpoint(webservice, mvc action). To this you'll need to make a HTTPRequest to the endpoint. The following code is what I use to make to POST the code.
public bool Post(string url, string body)
{
//Make the post
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
var bytes = Encoding.Default.GetBytes(body);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
Stream stream = null;
try
{
request.KeepAlive = false;
request.ContentLength = bytes.Length;
request.ContentType = "application/x-www-form-urlencoded";
request.Timeout = -1;
request.Method = "POST";
stream = request.GetRequestStream();
stream.Write(bytes, 0, bytes.Length);
}
finally
{
if (stream != null)
{
stream.Flush();
stream.Close();
}
}
bool success = GetResponse(request);
return success;
}
public bool GetResponse(HttpWebRequest request)
{
bool success;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Created)
{
throw new HttpException((int)response.StatusCode, response.StatusDescription);
}
var end = string.Empty;
using (StreamReader reader = new StreamReader(responseStream))
{
end = reader.ReadToEnd();
reader.Close();
success = JsonConvert.DeserializeObject<bool>(end);
}
response.Close();
}
}
return success;
}
So now you have can POST JSON to an endpoint and receive a response the next step is to create the endpoint. The following code will get you started on an endpoint in mvc that will receive an application and process it.
[HttpPost]
public ActionResult SubmitApplication()
{
//Retrieve the POSTed payload
string body;
using (StreamReader reader = new StreamReader(Request.InputStream))
{
body = reader.ReadToEnd();
reader.Close();
}
var application = JsonConvert.Deserialize<Application>(body);
//Save the application
bool success = SaveApplication(application);
//Send the server a response of success or failure.
return Json(success);
}
The above code is a good start. Please note, I have not tested this code.
You have obviously more than one client for the data & operations. so a service is what you are looking for.
ASP.NET MVC is a good candidate for developing RESTful services. If you (and your Manager) are ready to use beta version, Then Checkout ASP.NET-Web API.
If you want to stay with a stable product, Go for MVC3. you may need to write some custom code to return the data in XML as well as JSON to server different kind of clients. There are some tutorials out there.
So create a Service (ASP.NET MVC / WCF Service) .You may then create 2 client apps, one for the external clients and another for the Internal users. Both of this apps can call methods in the Service to Create/ Read the user accounts / or whatever operation you want to do.
To make the apps more interactive and lively , you may conside including a wonderful thing called SiganalR, which helps you to get some real time data without continuosly polling the data base/ middle tier very in every n seconds !

Resources