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.
Related
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 really new to web development, and I don't really have a good grip on the main concepts of web. However, I've been tasked with writing an asp.net application where users can search documents by querying an external RESTful web service. Requests to this REST service must be authenticated by HTTP Basic Authentication.
So far so good, I've been able to query the service using HttpWebRequest and HttpWebResponse, adding the encoded user:pass to the request's authorization header, deserialize the Json response and produce a list of strings with url's to the pdf documents resulting from the search.
So now I'm programmatically adding HyperLink elements to the page with these urls:
foreach (string url in urls) {
HyperLink link = new HyperLink();
link.Text = url;
link.NavigateUrl = url;
Page.Controls.Add(link);
}
The problem is that requests to these documents has to be authorized with the same basic http authentication and the same user:pass as when querying the REST service, and since I'm just creating links for the user to click, and not creating any HttpWebRequest objects, I don't know how to authenticate such a request resulting from a user clicking a link.
Any pointers to how I can accomplish this is very much appreciated. Thanks in advance!
You probably want to do the request server-side, as I think you're already doing, and then show the results embedded in your own pages, or just stream the result directly back to the users.
It's a bit unclear what it is you need (what are the links, what do you show the users, etc.), so this is the best suggesting I can do based on the info you give.
Update:
I would create a HttpHandler (an .ashx file in an ASP.NET project), and link to that, with arguments so you can make the request to the REST service and get the correct file, then stream the data directly back to the visitor. Here's a simple example:
public class DocumentHandler : IHttpHandler {
public Boolean IsReusable {
get { return true; }
}
public void ProcessRequest(HttpContext context) {
// TODO: Get URL of the document somehow for the REST request
// context.Request
// TODO: Make request to REST service
// Some pseudo-code for you:
context.Response.ContentType = "application/pdf";
Byte[] buffer = new WebClient().DownloadData(url);
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
context.Response.End();
}
}
I hope you can fill in the blanks yourself.
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.
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.
I have a .NET webservice that is returns JSON.
The client-side developer now wants to send his request in GET method, putting the parameters in the querystirng.
I have enabled the GET verb in my web.config file, I have added UseHttpGet=true in the ScriptMethod attribute, and now I am able to recive the parameters.
BUT when he calls the method using the URL he gets back XML.
Can anyone tell me how he can use a simple URL to invoke the method and get JSON as a response?
My webservice:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json,UseHttpGet = true)]
public string HelloWorld(string str)
{
return str;
}
the call he makes is http://Mysite/Service/Service.asmx/HelloWorld?str=hisValue
You have to instruct your client-side dev to set the request content-type header to 'application/json'. The service should then serialize results as JSON.