ASP.Net MVC: Creating an Area for json requests - asp.net-mvc

Just wondering what people think about creating an area to hold/manage json based requests (note I am thinking mostly get data not post data). I know its not your typical use of an area (i.e. normally you would create a different area for blog vs forum) but I am getting to the point where my project isn't huge but I definitely have a a lot of json stuff which seems to be confusing the issue and is making things look "unclean".
For instance, at the bottom of each controller is where I am putting json actions and so that they don't get mixed up with the other actions I prefix them with json - I shouldn't have to do this... Also I have specific view models for json which I have to prefix with json as well... etc, etc.
It would seem much cleaner to have them off in their own area and be able to drop the json prefix all together and have that defined by the area... what do you think or is this a bad idea?
Cheers
Anthony

I think it's a good idea. Having an asynchronous area where all controllers implement only asynchronous actions will certainly clean up your code. The problem will come when your project does become so big you want to expand into regular areas, then you'll end up with some naming conventions that might end up a bit messy.

You could also just create a separate controller for your json actions. I think this makes more sense than creating an area. Do you need json specific views, content, model etc or just some asynchronous actions?

I think that it's not nessesery to create separate area or even separate actions. If the actions return the same data and differ only in the type of the request - ajax or non-ajax you can just check what is the request and use the corresponding data format.
public ActionResult Index()
{
MyViewModel model = DataAccess.GetMyViewModel(); // Data access code
if (Request.IsAjaxRequest())
{
return Json(model);
}
else
{
return View(model);
}
}

Related

Is returning different view with object bad practice in ASP.net MVC 5?

I need to pass objects between ActionMethods and Views in an ASP.net MVC 5 app.
I'm using it for a multi page signup - and for a multi page payment.
Is this bad practice? I haven't seen a good way to pass objects between different controllers.
Code:
public ActionResult Join1()
{
//
return View("Join2", MyObject);
}
[HttpPost]
public ActionResult Join2(MyObject MyObj)
{
//manipulate object
//return
}
It seems to be an effective way to do it - though I haven't seen many people do it this way. I haven't seen objects being passed between action methods much at all.
Is there a flaw in this approach, a better way of passing models between Views - or should each ActionMethod stick to passing simple data with, say, TempData instead of objects?
Why haven't I seen any sample projects doing things like this?
I've seen return RedirectToAction("act"); plenty - but that is Get and passing an object in a URI is limiting - and I don't want users to be able to manipulate or see the data being passed.
thx.
Unless I have misunderstood the description, your code is not doing what you think it's doing. That first return View("Join2", MyObject); statement is not executing the second ActionMethod, it is only passing your data into the View that happens to have the same name as the second method. Therefore the code implied by //manipulate object will not run before that View is rendered and sent back to the user.
Assuming the View file Join2.cshtml exists, and it contains the default #using (Html.BeginForm()), then users submitting the form will cause the Join2 Action to be executed and the same view rendered with the manipulated data - unless, of course, you add another return View() statement that names a different View.
The reason you haven't seen this done much is that the MVC convention is to have a View named the same as the ActionMethod, this makes the code slightly simpler and also much easier for other ASP.NET developers to understand because it is what they are expecting to see.
If you want the form rendered by each View to then execute a different ActionMethod when it is posted back, the place to do that is in the View code, where Html.BeginForm() has several overloads that allow you to do just that, e.g. in Join.cshtml you could write:
#using (Html.BeginForm("Join2", "JoinController"))
{
// form fields and stuff
}
// Produces the following form element
// <form action="/JoinController/Join2" action="post">
To address the final part of your question, "I don't want users to be able to manipulate or see the data being passed", sorry to say it but your proposed code doesn't prevent that: users can see the data in the web form, before it is ever posted back to the Join2 method; they can manipulate the data by sending an HTTP POST containing any data they want back to the Join2 method.
If you absolutely, positively need to actually execute Join2() from within Join(), before anything is passed back to the user, then you can call it just like any other C# method:
var myResult = Join2(MyObject);
Then you have an ActionResult object that you can manipulate or return straight to the browser. But why you would want to do this, is beyond me.

Purpose of viewmodel in controllers when data already present

What is the point in using a viewmodel when all the relevant data is already available through the parameter in the signature of the controller? I've seen a lot of examples similar to this:
public ActionResult Index(BasicPage currentPage)
{
var model = new BasicViewModel { Heading = currentPage.Heading, Body = currentPage.MainBody, MyBlock = currentPage.MyBlock };
return View(model);
}
Why not just send in the "currentpage" in this example directly to the View? Is there something that is considered bad practise by doing like that?
The above was a general question for asp.net-mvc. I'll add a question about Episerver as well here as well and if I'm lucky someone can answer that as well.
When looking through the Alloy site done with MVC I also saw similar behavior like above where a viewmodel is created in all controllers, why not just send in the Page that is sent into the controller directly to the View? It seems like an unnecessary step to create the viewmodel? Most likely I'm missing some important point here =)
The idea behind viewmodels is that they are optimised for presentation. If you use domain objects you end up having to put logic into the view itself to control the way things are displayed. Putting logic into the view is poor design so the viewmodel gives you some flex so that you have this logic managed in a more appropriate place.
In addition, you can make your viewmodel simpler, only including the fields that are required for the specific view.
Your code example is not a good idea I agree. But having a view model is a good pattern. You might not need it right away but having a view model available and in place is a good option to have for upcoming additions. I would go with Joel's concept from his MVC templates: http://world.episerver.com/Download/Items/EPiServer-CMS/EPiServer-7---CMS/EPiServer-7-MVC-Templates/

Returning XML or JSON depending on the HTTP request

I am trying to develop a RESTful Web service as an ASP.NET MVC 3 Web Application.
(I know, I should use the right tool for the job, which in this case means I should use WCF. But WCF has too many abstraction layers and is thus too big to fit inside my head. It would be cool for a research project, but I am trying to do my job. Besides I previously tried it, and now I am of the opinion that, despite its big promises, WCF sucks big time.)
Anyway, what I want to do is simple: I want my Web service to return its results as either XML or JSON, depending on the type specified in the HTTP request (by, default, JSON). How do I do that?
A Json action result already exists. MvcContrib has an XML action result you can return, or you could just use Content (xmlContent, "text/xml") as your action result.
You can query the accept header to determine which action result you would like to return. As long as your action method returns type ActionResult, it doesn't matter which type it returns.
That said, once you prove the overall concept, there are better ways to structure what you're trying to do.
A quick solution is to create an optional parameter on your Controller method, and return the view as the appropriate format.
public ActionResult GetFormattedResults(string format)
{
var data = GetResults();
ActionResult result = new JsonResult(data);
switch(format.ToLower())
{
case "xml":
result = new XmlResult(data); // this class doesn't exist in MVC3 you will need to roll your own
case "html":
result = new View(data);
}
return result;
}
You could also wrap the formatting functionality into an ActionFilter so you can reuse the functionality across controller methods.

Symfony 1 - set JSON content type automatically for every AJAX request

In my webapplication, I always reply with JSON to AJAX calls.
Thus I find myself doing this on a lot of actions:
if ($request->isXmlHttpRequest()) {
$this->getResponse()->setHttpHeader('Content-type', 'application/json');
return $this->renderText(json_encode($details));
}
Is there a way to get that automatically: anytime the request is AJAX, the content type is JSON?
I was thinking I should use a filter maybe but I am not familiar with filters and maybe there is a better solution.
Any suggestion will be more than welcome.
Thanks,
Dan
The way I solved it:
Create a new class myActions which extends from sfActions. In this class create a new function renderJson($data):
protected function renderJson($data) {
$this->getResponse()->setHttpHeader('Content-type', 'application/json');
return $this->renderText(json_encode($data));
}
Now let your controller class inherit from myActions (instead of sfActions). And at the end of your controller just return $this->renderJson($data);.
(I also did some templating. in the renderJson, if the sf_debug is set in the config, and it's not requested through XmlHttp.)
I'm using a similar technique in one of my projects, but I'd suggest also taking a look at this article regarding iPhone optimization. You can set your routing to accept a format and return the appropriate template based on that. Then you don't need to set the header as it's set by the requested format.
Of course, this means you'll need to create separate template files for each output template, which seems a bother, or use a particular layout file and skip the template. So in the end it may amount to pretty much the same thing (or same amount of code, at least).

Is it OK to send a 301 redirect with an action filter?

I'm writing a new asp.net mvc application and I've been toying with the idea of allowing my user to post short, concise urls to content that he has posted. Those short url's will be handy in cramped spaces like Twitter and comment areas. I like this idea as I'm not a huge fan of url shorteners because they're so vague and you're never really sure what you're going to get. Instead of using a url shortener I want to give my client the ability to post:
http://domain.com/p/234
which does a 301 redirect to:
http://domain.com/2009/08/10/this-is-the-content-title
Now, this is a pretty simple process with a couple of extra routes and a custom ActionResult. The custom ActionResult I implemented is an extension method on a RedirectToRouteResult... It's fairly straightforward but about 20 lines of code nonetheless. I played around with doing the same functionality, only this time with an ActionFilter. My action filter looks like:
public class PermanentRedirectAttribute : ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.StatusCode = 301;
}
}
and my action method looks like (I removed a bunch of code to simplify):
[PermanentRedirect]
public ActionResult ShortUrl(int id)
{
return RedirectToAction("Post", id);
}
My question is this: Did I miss something or is it this simple? I've found some other posts where people are looking to do something similar and they always create a custom ActionResult. Besides using less overall code, given that this behavior may need to be used elsewhere on other action methods, I don't see why it shouldn't be an ActionFilter. With that being said I'm fairly new to the Request and Response objects so I'm not sure if I'm missing something.
The code you have shown will work just fine. However, I recommend using a custom action result instead of using an action filter.
One reason for this is that it will provide more information for your unit tests since there are fewer things to verify. That is, with a custom action result you can verify that the right type of result was used and that it has the right properties set on it. With your current design you'd have to separately verify both the action result data and that you correctly applied the attribute.
Another reason is that the code will be cleaner: There will be fewer things for other developers (or you in 2 weeks) to look at or understand. Looking at a simple return PermanentRedirectToAction("Post", id) is much easier than looking at an attribute and the return data.

Resources