RedirectToAction and partial views - asp.net-mvc

I'm curious why it's made exactly like that?
If i call this through AJAX:
public ActionResult Foo(){
return RedirectToAction("SomethingThatReturnsPartialView","Bar");
}
It won't return me partial view in AJAX callback but will redirect to url that represents action.
So - why it is so? What are possible workarounds?

Because when the browser receives the reply from the server that is a HTTP 30x redirect, it will do just that, regardless of how the request was initiated, either synchronously or asynchronously.
On of the possible workarounds could be something like RenderViewToString, but as we know MVC lacks this feature yet. It's a known missing feature everyone wants to get.
Look in this discussion: Render a view as a string
And also look here, there may be an option to prevent the browser going redirect with JavaScript: Catching 302 FOUND in JavaScript

Related

Asp.net mvc 4 RedirectToAction slow

When I use RedirectToAction("MyView", "MyController") sometimes the redirection is very slow to render the destination view.
It doesn't always happen.
I am using ASP.net MVC4 with IIS7.5
How can I prevent this problem and speed up the redirection?
I will put this here as code will not show very well in the comments section. If the action method you are redirecting to is in the same controller you are currently in, it is simpler and more efficient to call that method directly and return its results instead of the redirect response generated by the RedirectToAction method. Just to make sure we are on the same page, RedirectToAction actually returns a redirect response (302) to the client asking it to issue a new request to the action method you have specified as per MSDN http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.redirecttoaction(v=vs.108).aspx. Some code to illustrate:
public ActionResult MyAction(){
//do some work here
Return View(MyModel);
}
public ActionResult ActionIAmCurrentlyIn(){
//Do Soe work here
return RedirectToAction ("MyAction", "MyController"); //This costs an extra trip across the wire
return MyAction(); // Does same thing but without the extra trip to the client
}
This overhead of the extra trip becomes more significant if there are parameters being passed along to "MyAction" and as the network speed goes down.
Responding as an answer because I don't have enough rep to add a comment...
#JTMon In your code the "return MyAction();" can cause potential issues because the "MyAction" action will actually try to load a view named "ActionIAmCurrentlyIn" since that is the action that's specified in the route values (at least I assume that's where it's getting it from, I haven't actually dug into the code to find out).
This can be resolved by specifying the view name in MyAction:
return view("MyAction", MyModel);
To prevent this problem and speed up the redirection use:
return Redirect("~/MyController/MyView");
This approach will not change client-server interaction.
You can use RedirectToActionPermanent("View","Controller"); for it.

How to call a function *only once* in ASP.NET MVC page cycle

I have an ASP.NET MVC web app and have a function that I need to call when the page loads only once. Right now I have the function being called from a base controller OnActionExecuted.
The issue I'm having is that this function is called multiple times - once for the page, and then multiple times for different ajax calls that I have on the page. I've tried putting the function on Controller Initialize but this is also called for each ajax call to a controller action. So is there some function in the ASP.NET MVC page cycle that only gets called when a page is requested (GET) and not for all of the ajax calls (POST)? The only thing I can think of is putting all of the ajax calls in separate controllers that don't inherit from the base controller but there must be a nicer solution.
Depending on how you're doing your AjaxRequests you could use something like the following:
public ActionResult Index()
{
if (!Request.IsAjaxRequest())
{
LoadConfiguration();
}
// Rest of Action method (snip)...
}
This works if, for instance, you're performing Ajax with the jQuery JavaScript library which sends a special token to the server to indicate that it's an Ajax call (I'm sure other libraries do this). This might be better just in case someone changes the JavaScript code to perform GET Ajax requests.
One thing you mentioned does intrigue me though "The issue I'm having is that this function is called multiple times" - actually 'technically' this is not true. It IS only getting called once....per request, all those Ajax calls are treated as separate requests by the server, as if the user is requesting a page via the web browser. It sounds like what you really need is a way to differentiate between web page HTTP Requests, and Ajax HTTP Requests, hence the above solution.
It came to me right after posting the question...
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
if (Request.HttpMethod == "GET")
{
LoadConfiguration();
}
}
You can either do this work in the application scope (on start, in global.asax or other similar approaches), or store a configuration object in the session (or a flag to identify it has already been done, if there is nothing to store).

Rendering a View in MVC then immediately redirecting

What I am trying to do is render a View in an MVC site informing the user to not refresh their browser while server side processing is taking place. This could be a long running task, and if they hit refresh it will send the request again, thus sending them to the error screen when the process was actually successful. I was going to do this in JS, either with JQuery $.ajax(...) or with a simple $(document).ready(function() { window.location = ... }); but I was hoping there was a way to do it in MVC, thus giving me more control over the HttpResponseCode which is returned to the client calling. Is there a way to do this?
I was thinking along the lines of
public ActionResult LoadingAsync(string UserKey, string userInf)
{
AsyncManager.OutstandingOperations.Increment();
CallProcess(...)
return View();
}
then have a Completed Action perform the redirect
public ActionResult LoadingCompleted()
{
LongRunningProcess();
return Redirect("http://yourdone.com");
}
or just have something that Renders inside the view that will perform the Redirect from inside the View
<% Html.RenderAction("Process"); %><!--This won't actually redirect-->
Any ideas?
There is no way to achieve this without invoking some kind of Javascript on the client.
When you return a response to the user, you either return a page to display with an HTTP code of 200 (OK), or an instruction to redirect with an HTTP code of 301 (Moved Permanently) or 307 (Moved Temporarily) and a URL to redirect to.
You have to choose either of these return values and cannot return both.
The simplest solution is to use Javascript to redirect the user from your "please wait" page to the destination once it determines the background process has completed.
One simple solution would be to fire off your background process, then display a page which (1) asks the user not to refresh, (2) polls the server every couple of seconds via Javascript to determine if the background process is complete, and (3) redirects upon determining that it is complete.

ActionResult return to page that called it

I have a ActionLink, that calls my public ActionResult, and I would like it to return back to the page that it was called from, but how?
There are a couple of tricks that you can use for this.
The simplest is ...
return Redirect(HttpContext.Request.UrlReferrer.AbsoluteUri);
AbsoluteUri may not give you the exact path you are looking for, but UrlReferrer should have the imformation you are looking for. Redirect returns a subclass of ActionResult so it is a valid return value.
Another idea is to base the redirect location off of stored values. This is useful when you are going to make multiple requests before you want to redirect, such as when you validate a form and show validation issues on the first response. Another situation will be when the referrer is not a local site. In either case, your referrer won't be what you want it to and you will need to retrieve the correct location from somewhere else.
Specific implementations include using a hidden input field on your form, session state, pulling a descriminator value from your route data, or even just a more constant value like HttpContext.Request.ApplicationPath.
Good luck.
Keep in mind that due to the state-less nature of the web, your ActionResult isn't "called from" your ActionLink as much it is simply a url that the user-agent requested.
Because of this, the only real "built-in" way you can know where that user was coming from is by inspecting the http Request headers to see what the referring page was:
string referrer = Request.Headers["referer"];
You'd then be responsible for parsing out the Action method from this url, if you were going to call it directly. Be aware that this referrer may not be a link within your own site.

Would you ever want an action method to not return an ActionResult?

In ASP.NET MVC the convention is that a controller action method should return an ActionResult (or a type derived from ActionResult).
However, you can write a public method that returns pretty much anything and if that method is called (from a browser) the framework will package the return value up as a ContentResult and the browser receives a page of plain text.
This is all very interesting - but would you ever want to do this?
When you want to render something directly from your controller? e.g. using Response.Write(...); (or using other Response methods).
Not returning anything from an action method is essentially not responding to the client's HTTP request with a response.
An empty request might make sense in some cases (HTTP status being enough of a reply), but all web application patterns return something more than this (including, if I understand it correctly, REST: the new state of the entity).

Resources