Download XML client-side, fetch data from Session first - c#

My goal is to have the user be able to download some information currently stored in Session. There are multiple key/value pairs in Session I would like to have the user download as one XML file.
The control I am working with has a client-side 'onClick' event exposed. I was planning on calling a PageMethod to extract the data I wanted from Session, and return that data to the client.
I've seen a very clean implementation of this in MVC and I am wondering if this clean implementation is possible in ASP.NET AJAX, as well. If not, I am wondering what the best route would be to go for this.
In MVC/JavaScript I see something like this:
location.href = "../WorkOrders/Export/" + workOrderID;
public ActionResult Export(int id)
{
WorkOrderPdfExporter exporter = new WorkOrderPdfExporter();
byte[] buffer = exporter.Export(id);
return File(buffer, "application/pdf", String.Format("workorder#{0}.pdf", id));
}
This Export method returns a FileContentResult which is an MVC thing. I am wondering if something like this exists in ASP.NET AJAX, and if the datatype is suitable to return for a Page Method.
If not, what should I be doing here? I was thinking about creating a dictionary, sticking the relevant session objects into this dictionary, serializing it to XML (I have a Serializable Dictionary class implemented), ...and then attempting to return that XML for download?
Thanks for your time.

You can write directly to HttpResponse.OutputStream - you will need to set the correct ContentType too.
The code example for OutputStream is rather verbose (mostly dealing with a dynamically created image), but if you ignore those parts, you will have a basic function that will need minor modification for your use.

Related

Why Using JSON in MVC application?

First i would like to apologize if this is a stupid question.
While learning MVC i came a cross creating a strong type views based on model which for example will display all Users by 2 different functions, first will return a View passing a collection of users second will return a collection of JSON objects. so my question is, as i'm not familiar with JSON and for me using Models are more clear, why then using JSON in MVC?
In short why using:
var users = _db.Users
.Where(r => r.Name.Contains(q))
.Take(10)
.Select(r => new { r.Name,r.LastName,r.Address.Country });
return Json(users, JsonRequestBehavior.AllowGet);
In place of:
var users= _db.Users
.Where(r => r.Name.Contains(q))
.Take(10);
return View(users);
Maybe this is a bad code example, but why converting Models to Jason before passing them to a view, if we can directly pass the models.
For the first code snippet, it is more likely that it is used for a ajax call to seamlessly load the data from the server to the client and perhaps keep refreshing it without reloading the page. Also, the Users entity may have much more information than needed by the client, so the first example is reducing the information served and doesn't require you to create a new model to represent it.
The second example would be a controller action actually returning a view and that view is strongly typed.
If you would make a project that uses the WebApi, you wouldn't return views, you would expect the client to ask for data and that the client renders it how it sees fit.
If you want the call to return HTML that can be rendered in a browser, you would return a View, which basically takes the data and applies it to an HTML template.
If you want the call to return data only (most likely to be processed by an AJAX request), then you would return JSON.
The first is going to return JSON with a content type of application/json while the latter will return html with the content type text/html (after the appropriate View Rendering Engine has rendered the view in question) - they can be considered two different representations of the same resource. You may want to return JSON in response to a request made via AJAX and return only the data from the model that is required, but you may want to return HTML in response to a "normal" request.
out of the box, ASP.NET MVC does not support Content Negotiation, that is, make a request with the Accept header set to a particular MIME type will likely not yield a response with the expected content type - controller actions will in the majority of cases be configured to return a resource in one particular content type (usually html). ASP.NET Web Api on the other hand does support Content Negotiation out of the box.
JSON (= data only) is generally used in asynchronous (AJAX) requests as they can easily be processed by Javascript, while Views are styled HTML responses ready to be displayed by the browser.
Client side libraries understand JSON very well, so if you want to parse the result and manipulate them using a client side framework/custom scripts, then JSON is a better option (AngularJs is one example).
In Addition to your question, when using JSON, first you convert Model to JSON but when you users post a request you might reconvert JSON to model in order to persist result to DB. :-)
I

Handling Parameters of ASP.NET MVC Application

I am working on ASP.NET MVC 4 Project of our Company. It is revenue based application and It has some Filters at every Controller and Action of the application.They are Year and Quarter like some filters. for these filter changes I used Create Base Model, (It contains these filter values) and every other Models inherit from this Base Model.Base Model is use at #layout view.
Every change of filter should update the view.
Base Model in layout view something like this
public class BaseModel
{
public string YearSelected{ get; set;}
public string QuarterSelected{ get; set;}
}
and other Models are inherit from this BaseModel
public class RevenueModel:BaseModel
{
// other stuff
}
For all these things I am sending through the parameters.Seems like now Parameters are increase requirements are changes to add more parameters
1.I want to know the method that handle is correct and If method is insufficient Suggest me best
way to handle this parameter changes.
2.In the UI(View),
When user change the view by checking radio button and click on apply filter button I am using jquery for handle this,
window.href='Url Action with new Parameters';
window.href='#Url.Action("SomeAction","Controller",new{ // those all parameters } ';
When button click window.href will automatically call and update the view I want to knowIs this method Robust? Suggest me best way to handle this scenario.
"Simply I need a answer for if i use jquery to call an action and use high numbers of parameters for the call controller action"
What you're doing is doable, but as #ps2goat points out, you can run into issues if you have too many GET parameters in the URL.
But the right answer depends on how the filters will be used. Will the user often change the filters or will he rarely change them? If the user is expected to browse through your app and only rarely change the filters, I would suggest you to use another approach than including the parameters as GET parameters in the URL because:
You could run into problems if the total length of your URL becomes too long, as #ps2goat points out.
You could run into user experience problems. If a user bookmarks a page, and then later changes his filters, and uses the bookmark to return to the earlier page, his filters would be reverted, which is probably not what he would have expected.
It wouldn't look very pretty. All your urls on your site would look like /controller/action/?YearSelected=2014&QuarterSelected=1&Parameter3=2&Parameter4=8, which could also create SEO issues you would need to take care of.
In that case, I would recommend you to consider using a cookie or saving the user's filters on the server instead. (But preferably not in a Session, as that can create scalability problems for your application). If you used a cookie, the user's filters would be available to your Controller Action on each request automatically, as the cookie would be sent along with every request. (This is of course also something to have in mind when considering which strategy to use. If you have alot of cookie data, this will slow down the perceived responsiveness of your application, as the cookie data has to be sent along with every request to your server. So keep your cookie data as small as possible)
On the other hand, if you expect the user to change the filters often and maybe even several times on the same page, you could consider using jQuery to do an asynchronous POST to your MVC controller, retrieve the neccessary data using JSON, and update the view. This is actually not as difficult as it might sound.
What you would need to do to implement it, is to create a Javascript function on your page that submits your parameters to your controller action. You can send the data as JSON to the controller action also. Something like this could work: (Untested code)
<script>
function submitFilters() {
var parameters = {
parameter1: $('#parameter1').val(),
parameter2: $('#parameter2').val(),
...
};
$.ajax('#Url.Action("SomeController", "SomeAction")', {
contentType: 'application/json',
data: JSON.stringify(parameters),
success: function(data) {
alert('Received data back from server. Ready to update the view.');
}
};
}
</script>
Then you would hook up the filters (Radio buttons, drop downs etc) to call the method submitFilters.
MVC automatically converts the JSON data it receives from the client into your C# ViewModel as long as the property names match. Then you can do whatever querying and filtering you need to on the server, and then send the data back as the result of the action. (Pseudo code)
public ActionResult SomeAction(MyViewModel vm)
{
var data = SomeRepository.GetData(vm.Parameter1, vm.Parameter2, ...);
return Json(data);
}
Then you just need to update the view when the data is received. You would preferably use a template engine for that, but it's not required of course.
This is just a crude example of how you could do it. Normally I would create a Knockout View Model to encapsulate it all. But this should get you started.

pass value from apicontroller to view in asp.net mvc4

I have list of data in my api controller.
I want to pass this data to view using something similar to viewbag.
I know we cant use viewbag in apicontrller , So Is there any alternative for it.
Normally ApiControllers do not return views. They return models, or HttpResponseMessage for that matter. So you could simply have a view model that will contain the required property and then have your API action return this view model.
You are not supposed to tho that, the API controllers return only data (XML, Json, etc). So you should have two controllers:
System.Web.Http.ApiControlle Use this to return collections of data for example:
public List<Company> Get()
{
return this._companyService.GetCompanies();
}
Returns a list of companies in Json or XML not a view.
System.Web.Mvc.Controller use this one for returning HTML without data for example an HTML table without rows or client-side templates.
How to link the two? The idea is to render in the client-side with JavaScript, there is a good few reasons to do it this way, the main ones are that you have data and presentation in two completely separated feeds so you will be able to re-use your data feed (in mobile apps for example).
To render in the client-side is good idea to use some JavaScript rendering engine, take a look to http://handlebarsjs.com/.
Use Jquery.getJSON() to get your JSON and get your handlebars template from your DOM or via Ajax, select a DOM alement to insert the generated HTML. Once you have the JSON, template and container use the function below:
function RenderJson (json,template,container) {
var compiledTemplate = Handlebars.compile(template);
var html = compiledTemplate(json);
$(container).html(html); //set new content
}
I know it can seem like a more complicated process but it you try it you will see the advantages, you will be able for example to test your data feed and your data presentation separately.
Hope it helps :)

ashx method call - make reusable

i have an ashx file that creates a binary csv file for me. i'd like to be able to pass it any generic list.
i know i can put the list in session and then pick it up in the generic handler but will that acceptable under heavy loads?
byte[] csvData = Utility.ToCsv(",", DAL.GetProducts());
context.Response.OutputStream.Write(csvData, 0, csvData.Length);
it would be nice if i can run any query within the handler (instead of hard-coding DAL.GetProducts()). what are some ways to do this?
If the dataset is above the threshold of what can be serialised into QueryString data, I would simply create a HttpHandler which accepts the list as serialised POST data. That way all your ToCsv() handler needs to do is get the list out of the post data and then deserialise it.
Let me know if you need me to elaborate on any of this.

Handling post requests in ASP.NET MVC

Recently I started working with MVC, before that I used "classic" ASP.NET.
After using Ruby on Rails (RoR), I wonder how to implement POST request handling in MVC similar to how RoR operates. In RoR you use the Post method, so you need only one function for a view.
In ASP.NET MVC I need to use 2 separate functions for GET and for POST, so I need to initialize the same data twice, and I don't like to repeat something in my code.
How can I check if the request is POST in one method?
Update:
Solution is found: I have to use Request.HttpMethod.
Thank you!
I came across this question wanting to know the same thing. Below is a detailed description of my situation and the solution that I used (which utilizes the other answers provided here). I originally tried to use the two separate method approach, but I ran into a problem when the method signatures of these methods became identical.
I have a page that displays report data. At the top of the page there is a form with some fields, which allow the user to specify report parameters such as start date, end date, etc.
I originally approached this by creating two separate methods to handle the Get and the Post methods. The post method would redirect the browser to the get method so that any parameters that were specified would be added to the query string and so that the browser would not prompt the user with a dialog saying that it is going to resend the data that they entered if they refresh. Note: I realized later that I could accomplish this by setting the method attribute of my form element to "Get", but I think ideally a controller shouldn't have knowledge of how a view is implemented, so in my opinion that is irrelevant.
As I developed these two methods I eventually found myself in a situation where the method signatures became identical. Furthermore, my code for these two methods became nearly identical, so I decided to merge them into a single method and to just check the request verb so that I could do something slightly different when the request is not a "Get". A distilled example of my two methods is shown below:
// this will not compile because the method signatures are the same
public ActionResult MyReport(DateRangeReportItem report)
{
// if there are no validation errors and the required report parameters are completed
if (ModelState.IsValid && report.ParametersAreComplete)
{
// retrieve report data and populate it on the report model
report.Result = GetReportData(report.CreateReportParameters());
}
return View(report);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult MyReport(DateRangeReportItem report)
{
if (ModelState.IsValid && report.ParametersAreComplete)
{
// redirect to the same action so that if the user refreshes the browser it will submit a get request instead of a post request
// this avoids the browser prompting the user with a dialog saying that their data will be resubmitted
return RedirectToAction("MyReport", new { StartDate = report.StartDate, EndDate = report.EndDate });
}
else
{
// there were validation errors, or the report parameters are not yet complete
return View(report);
}
}
Why am I accepting a model object as the parameter to my get method? The reason is that I wanted to take advantage of the validation logic already built into the model object. If someone navigates to my page directly with all parameters already specified in the query string, then I want to go ahead and retrieve the report data and display it on the page. However, if the parameters specified in the query string are invalid then I also want validation errors to appear on the page. By putting my model object as the parameter, the MVC framework will automatically attempt to populate it and will capture any validation errors without any additional work on my part.
I used the other answers posted for this question to create a RequestHttpVerb property on a base controller class in my project:
public HttpVerbs RequestHttpVerb
{
get { return (HttpVerbs)Enum.Parse(typeof(HttpVerbs), this.Request.HttpMethod, true); }
}
So finally my consolidated method looks like the following:
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult MyReport(DateRangeReportItem report)
{
// check if there are any validation errors in the model
// and whether all required report parameters have been completed
if (ModelState.IsValid && report.ParametersAreComplete)
{
// this is unnecessary if the form method is set to "Get"
// but within the controller I do not know for sure if that will be the case in the view
if (HttpVerbs.Get != this.RequestHttpVerb)
{
// redirect to the same action so that if the user refreshes the browser it will submit a get request instead of a post request
// this avoids the browser prompting the user with a dialog saying that their data will be resubmitted
return RedirectToAction("MyReport", new { StartDate = report.StartDate, EndDate = report.EndDate });
}
// there were no validation errors and all required report parameters are complete
// retrieve report data and populate that data on the model
report.Result = GetReportData(report.CreateReportParameters());
}
// display the view with the report object
// Any model state errors that occurred while populating the model will result in validation errors being displayed
return View(report);
}
That's my current solution to the problem. I would prefer not to have to check the Request.HttpMethod property in order to determine whether I needed to perform the redirect, but I didn't see another solution to my problem. I would have been fine with keeping two separate methods to handle Get and Post requests, but the identical method signature prevented this. I would have preferred to rename my Post action handler method to avoid the method signature conflict and to use some mechanism to indicate to the MVC framework that my renamed method should still handle the "MyReport" action, but I am not aware of any such mechanism in the MVC framework.
You only need separate methods for GET and POST if their method signatures differ, there's no reason why one action method can't handle GET and POST methods.
If you need to know whether it was a GET or POST, you could check using Request.HttpMethod in your action, but I would advise using a separate method decorated with the [AcceptVerbs(HttpVerbs.Post)] attribute as suggested by the other posters.
You don't check in ASP.NET MVC. You decorate your method with the [AcceptVerbs(HttpVerbs.Post)] attribute to indicate that the method applies to post only, and accept the model in the method used to handle the post.
I'd strongly suggest doing the walkthrough for NerdDinner to understand more about the ASP.NET MVC framework.
You may take a look at the Request.HttpMethod property.
Correct way to do is using ModelBinding during Post request.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(EmployeeViewModel model)
{
//validate data, save employee, handle validation errors...
}
This way you will not have to init your data again.

Categories