Return Data and File from MVC Action - c#

I have a MVC GET action that returns a json class model with a byte[] property, I use this to return a message and the file, but if the file is too big, I would get a OutOfMemoryException, is there any other way to return file and data that wouldn't use such memory?
I know I can create another action to return only the final file, but can I do it on the same request?
Edit:
I don't want to use byte[] or any method that will load the file into memory
public ActionResult GetFile()
{
// Here: currently logic to create the final file and the message
// Here: I want to add the final file to the result
// Here: I want to add my model data(json) to the result
// Here: currently returning json with a byte[] property to return the file
return Json(myModel, JsonRequestBehavior.AllowGet);
}

Depending on your restrictions you can do something tricky, if you are able to upload a file on the host, you can return the URL pf uploaded file in your JSON result and then let the user to download it.
In addition, you can find this link helpful https://stackoverflow.com/a/51526234/7855321.

Related

Is it possible to return an img to <img src=""> without serving it as static?

Right now I'm returning image from controller in C# with
return File(bytes, "image/jpeg");
and it works fine, but it literally returns file. Meanwhile I'd want to return images that will be displayed on the page but without making them static (so, if user gives somebody else url, then he'll have to log in in order to be able to access them).
The only way to do it that I managed to find is Base64 encoding, and it works fine, but it seems to be a kind of laggy for browser when the img size is increasing.
Maybe that's some kind of injecting images into .cshtml but it sounds like Base64
In your controller you have an action like this (exactly as you described):
public class PhotoController : Controller {
public ActionResult GetPhoto() {
...
return File(bytes, "image/jpeg");
}
}
If you're just pulling the file from the file system, you can do this (if the file is in your website folder):
return File("~/images/" + name, "image/jpeg");
Or if the file is outside of your website folder:
return PhysicalFile("C:\\images\\" + name, "image/jpeg");
Then in your page, you have an image that has a source pointing to that action:
<img src="#Url.Action("GetPhoto", "Photo")">
You create a separate "page" for the image that still just returns the image file. The page knows which image to show and whether to show based on the user and URL. So you might have a Images.aspx page and route map to your page like this:
/images/{imageID}
which could translate to Images.apsx?ImageID={imageID}. This "page" does not return any html... only the image, with an image/jpeg content type. Then the src attribute for your html <img element in the main page can point to your new route.
No matter what you do, the important thing to understand is you are using HTTP's request/response model. The <img element in the page should be supplied via a completely separate HTTP request, and not as part of the same request that provided the html.

C# transfer image via json. Error

I have c# client and c# server (mvc4 api controller) and I want to transfer image via json.
I write on the client:
var memoryStream = new MemoryStream();
image.Save(memoryStream, ImageFormat.Jpeg);
var baseStr64 = Convert.ToBase64String(memoryStream.ToArray());
response.Image = baseStr64;
(new JavaScriptSerializer).Serialize(response);
...Sending
Without image controller gets the request class normal, but with image base64 string field I have a null parameter in controller. Then I noticed that output json fails in online json validators on this base64 field.
My output json can be found here: http://pastebin.com/wnAJpZGV
How to transmit image correctly?
It is possible that the Json string is too big. The PasteBin example you showed was over 200K in length. Check this StackOverflow article on how you might be able to fix the problem:
Can I set an unlimited length for maxJsonLength in web.config?

Design - Log user downloads

I have to log the download requests for each file that is grabbed off of a website. This log has to have the Employee ID, Solution ID, IP Address. I've used quite a few methods -
First, I was using a model where I was putting the path of the file
in an anchor tag . Whenever the user clicked on this anchor tag, I
was generating an AJAX request to log the file download.
But the huge drawback of this is that the user can just copy the file and paste it in a seperate window to get the file. That would ensure that the download was not logged.
Second,
When I was processing the ajax request in the web method in a page. I tried transmitting the file through HttpResponse, but that didn't work either.
HttpContext.Current.Response.TransmitFile("filename");
jQuery ajax call kept failing, and I never got the file on the client side.
The key thing is, I have to do the whole thing without refreshing the page.
I'm wondering if this is possible at all...
You could implement a IHttpHandler that logs the request, retrieves the file and serves it. This way, even if the link is copied and pasted directly, it would still log it.
public class SimpleHandler : IHttpHandler
{
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
string fileToServe = context.Request.QueryString["file"];
if (!string.IsNullOrEmpty(fileToServe))
{
//Log request here...
context.Response.ContentType = "content type for your file here";
context.Response.WriteFile("~/path/" + fileToServe);
}
}
}
You could use the AJAX method, with an identifier in the link to be used as a parameter value to refer to the file - rather than storing the full path - and have your web method return the serialized data of the file.
So, your web method might look something like this:
[WebMethod]
public static string GetDownload(string someIdentifier) {
// get the contents of your file, then...
// do your logging, and...
var serializer = new JavaScriptSerializer();
return serializer.Serialize(fileByteArrayOrSuch);
}
Then handle the file contents on the client side. There will doubtless be some more trifling elements to add to your function for the sake of logging; but the bottom line is, your AJAX can both handle logging and then process the download request.
This is very much possible – you need to return a file as a response to an action (Mvc) or to an aspx page (webforms). So when the action or aspx page is hit you can log the request and write the file to the response.
Edit: for webforms example, see this SO question
For mvc:
public ActionResult DownloadFile(string fileHint)
{
// log what you want here.
string filePath = "determine the path of the file to download maybe using fileHint";
return File(filePath, "application/octet-stream"); // second argument represents file type; in this case, it's a binary file.
}

include asp.net filled javascript file

I have a javascript file (marker.js) which contains a json variable :
var markers = [
['Service1', 46.81865, -71.31838367115952],
['Service2', 46.81248956788163, -71.29209432884048],
['Service3', 46.80349635182245, -71.26580498652137],
['Service4', 46.81248956788163, -71.39725169811672],
['Service5', 46.821482783940814, -71.40138736927624]
]
In the main javascript, I insert this javascript file so main function can use it. => OK
Now, I want to fill dynamically this var so the coordinates are dynamically get from the database and inserted in the file. Of course, this file should not be written on the disk as an other user would need the same file but with different coordinates.
I think I should tell the server this js file should be interpreted by the asp engine and data retrieved in the codebehind then sent to the "js interface" but how do I do that?
I would appreciate an example of both a home page and the js.
Thank you for your help!
I would return JSON from the controller and include a method in the include file that accepts JSON like so:
function someFunction(json){
var jsonObj = JSON.parse(json);//object is built from json returned by the controller
}
You can call this controller method using AJAX when the main view loads and pass in the JSON from the ajax call

Can i pass a Model from view to controller without Form?

Hi guys i have difficulties of passing my model to controller> I wonder if this is a good practice or is it possible to do so. Here's what i want to achieve.
<% foreach (DownloadFile file in Model){ %>
click here to download
<% } >%
I want to pass the DownloadFile Object "file" to my controller that goes like this:
public ActionResult DownloadLabTestResult(DownloadFile File)
{
DownloadFile file = File;
...
return new FileStreamResult(Response.OutputStream, Response.ContentType);
}
I tried passing a string or integer and its doable. but when i want to pass an object like the above, i get a null value. What's the proper way to do this? thank u!
When using FileStreamResult, you need to give it the stream that represents the contents of the file, which will be consumed and sent to the client. Currently you've instead given it the ASP.NET response stream instead. It can't possibly read from that (it is an output-only stream).
So; where is the contents? Open up a stream to that and pass it in. Depending on your implementation, this could mean the local file-system, a network file-system, a database, a remote http (etc) server, or something generated in-memory (typically via MemoryStream).
Equally, it is for you to tell MVC what the content-type is; you shouldn't use the value from Response.*, since that is what you are constructing.

Categories