Can a httphandler in .net return a value? If yes how?
Thanks,
Subrat
The IHttpHandler interface only implements two things:
Boolean IsReusable {get;}
void ProcessRequest(HttpContext context);
So no... in the strictest sense it is not meant to return a value. Now, you can shape your response to look however you want it to (SOAP/XML/JSON). So in effect, you can return anything your heart desires so long as HTTP can support it, and the client consuming it knows how to deal with it.
However, it is ill-advised to go about trying to implement your own services via an HttpHandler as there are simpler and more efficient ways to accomplish the same thing.
The HttpHandler responses by its ProcessRequest(HttpContext context) method, in which you can modify the parameter context to tell what do you want to send back as an response. context.Response.ContentType specifies the MIME type of the response,for example the reponse is text/html so the browser will render it to an html page.Or the reponse is video/mp4 the browser will try to open it and in most circumstances the browser will show a download dialog. Unfortunately there is no text/array in the MIME type(and i think there won't be in the future). But you can pass your array value as plain text with special formats and deserialize it at client side. Here is a simple example:
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("[1,2,3,4]");
}
and at client side in javascript:
var response = GetTheResponse(); //maybe via ajax or something equivalent.
var myArray = eval(response); //myArray[0]=1,myArray[1]=2...
In a real project, you may want to get an array with complex objects in it(not just simple numbers). So you need systematized serialization/deserialization standards, for example, you serialize your array of Person object into json strings and write it to the reponse, and you deserialize them back at client side using some json utils.
Related
So, I configured an external (3rd party) service to send me data through push requests. There aren't many documentation on the format of this data, they just say to point for a URL that accepts POST.
So, I want to capture this message and add to a variable that I can add to a temporary database, and analyse it to create a proper treatment later.
All examples I saw show how to send and capture the response, but I just want to capture a random message that I don't know.
Any Hints?
Regardless of the format of the request they send to your application, everything will be contained within the HttpRequest object (which, if you're just talking about a Page or something similar, would/should be built-in as the .Request property of that page).
If the request has form values, the .FormData property on that object will be a NameValueCollection of those values. If it has something in the POST body, the .InputStream property on that object will contain that data. Files, headers, query string values, etc. will all be on that object.
You can copy whatever you like from that object into your data, inspect what you get, tinker to more specifically target the values they send you, etc. Without knowing the format of the data they're going to send you, anything more specific will require inspecting what they send you and reverse-engineering its format from there. But all the data will be in that HttpRequest object.
You can use the InputStream property of the Request object. This will give you the raw data of the HTTP request.
if (Request.RequestType == "POST")
{
using (StreamReader reader = new StreamReader(Request.InputStream))
{
var wholeRequest = reader.ReadToEnd();
}
}
If you just want the request body, you can use Request.Form.ToString().
if (Request.RequestType == "POST")
{
var wholeForm = Request.Form.ToString();
}
I would not use the .FormData NameValueCollection unless you know they will be using a content-type of application/x-www-form-urlencoded multipart/form-data. Other content types will not properly populate that collection.
I am making a Web Api and I need to return multiple images to the client. I am currently using a Base64 string for each image but this results in each request taking far too long. Is there a better, more efficient way of returning images?
This is the code I am using:
Controller:
public LearningUnits GetLearningUnits([FromODataUri]Guid key)
{
var record = db.LearningUnits.SingleOrDefault(inst => inst.LearningUnitId == key);
record.ImageURLPath = ImageHandler.ImageToByteArrayFromFilePath(record.ImageURLPath);
return record;
}
ImageToByteArray Method:
public static string ImageToByteArrayFromFilePath(string imagefilePath)
{
byte[] imageArray = File.ReadAllBytes(imagefilePath);
string baseImage = Convert.ToBase64String(imageArray);
return baseImage;
}
If the endpoint returns json, then there is no other way, beyond base64, how to embed binaries within the response. But it is definitely a bad idea due to the performance issues. May be for some icons it would be ok, but for larger images its not suitable.
So the best solution here, is to return the url to the image. And the client will make further request to get raw bytes for the image.
Also worth to mention, the image url can not only be the path to the static file, but also a path to some webapi endpoint, which, for instance, gets the image bytes by the resource id and sends the client raw binary back, and not a json string.
The solution is to use media formatters, so that when the Web API is queried with a particular type, you'll then receive the actual binary stream of the particular type.
http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters
This is the standard RESTful pattern; you have the same URL, but when you want a JSON record for the data, you accept-type:application/json, but you change your MIME request type to image/png or something similar when you want that media type.
More can be found here:
How to provide custom mediatype formats for OData Api
Odata also implicitly supports it here: https://msdn.microsoft.com/en-us/library/system.web.http.odata.formatter.odatamediatypeformatter(v=vs.118).aspx
I'm having an implementation of DelegatingHandler which basically take a request and address it to another server (http://localhost:9999/test/page.php --> http://otherSite.com/test/page.php ).
Following my question here, I now have to read the result of the page and edit it a little bit:
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
string url = request.RequestUri.PathAndQuery;
UriBuilder forwardUri = new UriBuilder(_otherWebSiteBase);
forwardUri.Path = url;
HttpRequestMessage newRequest = request.Clone(forwardUri.Uri.ToString());
HttpResponseMessage responseMessage = await _client.SendAsync(newRequest);
//HERE: How to read the responseMessage.Content in string?
return responseMessage;
}
I'm trying to read the content of the message, change some parts of it(basically change all http://otherSite.com into http://localhost:9999 ) and then return it.
The issues that I'm facing:
string content =await responseMessage.Content.ReadAsStringAsync();
Doesn't returns me anything that is readeable(I'm not sure, but I've the impression it's maybe because of the compression?)
Is there a way to replace the content of the message?
I'm trying to understand this a little better. Are you simply looking to make all requests that go to that address get redirected to another address? Given that you're putting this in the delegating handler, I'm imagining this is being run for every incoming request.
If that's the case, I don't really believe this is the location to write this code. There are two other places that I think provide a cleaner solution.
In the web server:
You seem to be recreating the idea of a Reverse Proxy (https://en.wikipedia.org/wiki/Reverse_proxy) where you want one server to simply direct requests to another without the client knowing about the change. You can make this modification on the server itself. If you're using IIS, there are guides to use IIS plugins like Application Request Routing to achieve this ( http://www.iis.net/learn/extensions/url-rewrite-module/reverse-proxy-with-url-rewrite-v2-and-application-request-routing ). Other web servers also have their own solutions but I have not personally tried them.
On the route itself
On whatever Web API route would be responding to this request, you can use http status codes to tell the browser to redirect the request elsewhere.
The 3xx series were specifically made to solve this kind of problem: http://www.restapitutorial.com/httpstatuscodes.html
That said, if you still want to use the approach in the original question, you need to ensure that there is a Media-Type Formatter for the data type that is being returned. By default, Web API will only attempt to use formatters for JSON, XML, and Form-url-encoded data. If you are returning anything else, you'll need to do a little more work ( http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters ) to get the data back to manipulate it.
Instead of returning a binary stream (MTOM/Base64 encoded) in the web-method itself (as SOAP XML) e.g:
[WebMethod]
public byte[] Download(string FileName)
....
return byteArray;
Can this method respond somehow with (maybe via the Server object)?:
Response.BinaryWrite(byteArray);
Pseudo:
[WebMethod]
public DownloadBinaryWrite(string FileName)
...
Response.BinaryWrite(byteArray);
Yes, it is possible. You need to change the return type to void since we're going to be writing directly to the response, and you need to manually set the content type and end the response so that it doesn't continue processing and send more data.
[WebMethod]
public void Download(string FileName)
{
HttpContext.Current.Response.ContentType = "image/png";
HttpContext.Current.Response.BinaryWrite(imagebytes);
HttpContext.Current.Response.End();
}
Note that WebMethod is not really supported these days, you should be switching to Web API or WCF (if you need SOAP support).
If you want to do BinaryWrite you probably want to write a separate IHttpHandler instead of a web method. Web methods are oriented around SOAP stuff, so hacking them into custom responses, while possible, is kind of odd.
I'm designing a web interface that is responsible for communicating with a piece of hardware. The hardware contacts the web page and sends an HTTP Request using POST that contains specific data in the body of http package using a "key=value" format.
Server-side I have code that does the following:
public override void ProcessRequest(HttpContext curContext)
{
if (curContext != null)
{
HttpResponse response = curContext.Response;
response.Clear();
response.ContentType = "text/plain";
response.BufferOutput = true;
response.StatusCode = 200; // HttpStatusCode.OK;
response.Write(response.StatusCode.ToString());
response.End();
}
}
But what I really need is the necessary code to review the Body and retrieve the data (which is in text/plain format). I'm fairly new to this type of web programming so I don't know exactly what code to write to look in the curContext to get this information, or if I even have my override method correct.
I was expecting to have something available like curContext.Request.Body but this isn't the case. How can I see the raw POST data in body of the Request? Can anyone point me in the right direction?
Thanks
You'll want to use the InputStream property on the HttpRequest instance returned by the Request property exposed by the HttpContext passed to your ProcessRequest method.
This will give you the contents of the POST request (which you can verify with a call to the HttpMethod property on the same HttpRequest).
Note that you'll have to use a StreamReader in order to convert the byte stream into strings which you'd then decode (since those key/value pairs should be url-encoded).
Fortunately, this is already done for you. On the HttpRequest instance, you can use the NameValueCollection returned by the Form property to check for the values passed as part of a POST request with url-encoded key/value pairs like so:
public override void ProcessRequest(HttpContext curContext)
{
if (curContext != null) return;
string value = curContext.Form["key"];
// Do other processing.
...
Note that you can also use the indexer on the HttpRequest, but that combines everything exposed by the QueryString, Form, Cookies and ServerVariables collections which I would say in this case is a bad idea, as you are specifically posting information and expecting that on the other side.
If you are putting the data in the body of the request in "key=value" format, it sounds like you are URL encoding form data (as long as you are delimiting the key/value pairs with an ampersand (&).
If that's the case, you should be able to use:
curContext.Request["key"]
And it will give you "value" in your example.