MVC3 Recommended Controller, Action query re-use - asp.net-mvc-3

In an MVC3 app what is the recommended method to store the Controller, Action & query details of a page and then re-use them in an actionlink on a subsequent page?
e.g. from page ~/Home/BlogsByTag?tag=Cloud%20Services listing a series of blogs, what is the 'best' way to capture the Controller, Action & query and then how can these then be applied to a 'Back to List' actionlink in a subsequent edit page (~/Admin/Edit/?Blog=1234)?

If i understand you right, you want to generate an ActionLink with the url from the referring page?
You can read the referrer from the request in terms of a complete url:
Request.UrlReferrer
If you want to have access to the action, controller and query parts, you have to pass them in the link as parameters. For example:
Html.ActionLink("Linktext", "Edit", "Admin", null,
new {
Blog = 1234,
ReferringController = "Home",
ReferringAction = "BlogsByTag",
ReferringQueryParams = ...
});
Then you can read that vals in the Edit Action and pass it to the View to generate the back-link.
But maybe using history.back() is a simpler approach.

You can use:
Url.RouteCollection["controller"]
Url.RouteCollection["action"]
...
For the variables you need. For the querystring you can use:
Request.QueryString["variable1"]
Alternatively you can declare the controller:
public ActionResult MyController(string controller, string action, string variable...)
and the variables will be automagically filled.
Then you can store this info (or the full url) on Session["refurl"] for example, which is valid for the rest of the user's session

Related

handle direct url with history api in asp.mvc

I have my site like http://mysite.com/ and on the index page i have search box and for the result i am using jqgrid. When user click row in the jqgrid row I am taking data from cells and do ajax call to server and fetch json data and once data arrived I hide the search box and jqgrid and show another div which is I kept for result. In short, user will be on the same page just div's hide/show.
Now I have seen history api and used pushState and popstate so my url becomes in the addressbar like http://mysite.com/controller/action/para1/para2 (here para1 and para2 are the parameters i am passing to action). Everything is ok so far.
Now the problem is if I copy this URL "http://mysite.com/controller/action/para1/para2" and if I open this with let's say different browser and hit enter it display just json data. So, I am confused that how to handle when user directly use that url in controller.
I was thinking to check in the controller action if the request is AJAX then return json data otherwise full page, is that right approach? OR something on the client side we have so that it load the same way as earlier.
Thanks
if I copy this URL "http://mysite.com/controller/action/para1/para2" and if I open this with let's say different browser and hit enter it display just json data.
it only display json data because its ajax call only so how to deal with that so that it also display the same page even user directly access the url.
I think what you're looking for is Request.IsAjaxRequest():
public class FooController : Controller {
public ActionResult GetFoo(int id) {
var model = _fooService.Get(id);
if (Request.IsAjaxRequest())
return PartialView("_Foo", model);
return View("Foo", model);
}
}
Note: It's recommended to use WebAPI controllers to handle only json data. So if the user got there by typing the url the mvc controller will handle it and if you need to get the json data for that view you could call the webapi controller.
Use a separate controller or action method for AJAX and for Views. The View controller should match the URL. The Ajax controller should be the less "pretty" URL since it's behind the scenes.
You need to set up a routing definition in global.asax (MVC 3) or App_Start/RouteConfig.cs (MVC 4) to handle the parameters if you haven't already done that.
routes.MapRoute(
"MyRoute",
"MyUrlController/{action}/{para1}/{para2}",
new
{
action = "Index",
para1 = UrlParameter.Optional,
para2 = UrlParameter.Optional
}
);
Then in the View controller:
public ActionResult Index(string para1 = "Default Value", string para2 = "Default Value")
{
// ...Handle parameters...
return View("_MyView", viewModel);
}
Returning a View object type is the key. The History API URL doesn't get it's data from the same AJAX source controller which returns a PartialViewResult.

MVC3 MapRoute to convert aspx query params into the route

I'm working on a project to rewrite an aspx site as MVC3. I want to make the old URLs work on the new site. I have named my controllers and actions such that the URLs actually contain enough info in the query string to route correctly but I'm having trouble getting the routing to work since it doesn't like the ? in the URL.
Basically I have old URLs like this:
www.example.com/Something/SomethingElse/MyPage.aspx?Section=DetailSection&TaskId=abcdef
I tried to create a route using:
routes.MapRoute(
"OldSite",
"Something/SomethingElse/MyPage.aspx?Section={action}Section&Id={id}",
new { controller = "Task", action = "Index", id = UrlParameter.Optional }
);
I want it to route to the correct new URL which is:
www.example.com/Task/Detail/abcdef
I know that all traffic to the MyPage.aspx page should go to my new Task controller and the beginning of the Section parameter always matches one of a few corresponding actions on that controller.
Unfortunately I have found that I get an error that a route can't contain a question marks. How should I handle this? Would it be better to use URL rewriting? Because this is a private site I'm not concerned with returning permanent redirects or anything - no search engine will have links to the site anyway. I just want to make sure that customers that have a URL in an old email will get to the right page in the new site.
In this one case I think the simplest way would be to have your old page mapped to a route:
routes.MapRoute(
"MyPage",
"Something/SomethingElse/MyPage.aspx",
new { controller = "Task", action = "MyPageHandler" }
);
And have this route mapped to an action method in TaskController:
public ActionResult MyPageHandler(string section, string taskId)
{
if (section.Contains("Detail"))
{
// execute section
}
}
This way you're treating your old site's query string for what it is: a query string. Passing those parameters straight into an action method is the most MVC-y way to interpret your old site.

Submit button which RedirectToAction to previusly page.

I have one method which I use in some place. Now I make RedirectToActio.... and back me to the concrete page. Is possible to make, it back to previusly page?
You could use the Referer HTTP header but it's not very reliable. A better way is to pass the url you want to redirect to the controller action (it's the way the POST LogOn method on the AccountController is implemented when you create a new ASP.NET MVC 3 application using the built in wizard. Take a look at it):
public ActionResult Foo(string returnUrl)
{
...
return Redirect(returnUrl);
}
Then when you call this action you pass the url of the current page. For example you could generate the following anchor:
#Html.ActionLink(
"do some processing and redirect back here",
"foo",
new { returnurl = Request.Url.AbsoluteUri }
)

Redirecting to action with a parameter

Let's say I have a website that displays info about books. The info about a specific book can be seen on a page with the url "/Book/Show/1234", where 1234 is the id of the book.
To edit the information about the book, there's a link on the book page that goes to "/Book/Edit/1234".
When done editing, I wan't to redirect the user back to the book page, i.e. back from "/Book/Edit/1234" to "/Book/Show/1234".
My problem is the going back part. I'm trying to use the RedirectToAction() method. I can specify which controller and which action in that controller to direct to (the "/Book/Show" part), but I don't know how to specify the id of the book to go to, i.e. the last part of the url.
The Edit action method recieves the id as a parameter, so I have access to it. I have tried this without success:
return RedirectToAction("Show", "BookController", id);
This redirects to the url "/Book/Show/". As you can see there is no id.
What is a good way to accomplish what I need?
Try this:
return RedirectToAction("Show", "BookController", new { id = bookId});
where bookId is ID of your book. And Show action looks like:
public ActionResult Show (string id) { ... }

Need help with ReturnUrl in MVC 3 LoginPage

I have this url in my login view: http://localhost:5550/login?ReturnUrl=/forum/456&theme=1
I get the right url value when I am in the login page.
As you can see I have 2 query string parameters: ReturnUrl and theme
So far good.
Now the login page posts a form to a controller action.
All I need is to read the values of these 2 query string params.
I just can't make it work.
This is my login page view:
#using (Html.BeginForm("try", "login"))
{
//set text boxes and button so user can try login
}
This is my controller where I need those 2 values:
[HttpPost]
public ActionResult Try(LoginModel model, string ReturnUrl, string theme)
{
//read all query string param values...but how?
//I am not getting anything in string ReturnUrl, string theme. They are null
}
Other part of the question:
I can debug other controller. But not this controller.
Is this because I am posting a form using BeginForm?
Doesn't make sense. But the breakpoint never hits even though I get error on browser.
Normally you shouldn't be reading from ReturnUrl. The flow works like this:
Request to controller action which requires authentication using the [Authorize] attribute
ASP.NET MVC adds the ReturnUrl and redirects to /Account/LogOn, automatically encoding and appending the ReturnUrl parameter
The Account/LogOn POST controller action, after authenticating the login information, redirects to the URL in the ReturnUrl.
I wrote about that in gory detail in the following posts:
Looking at how the ASP.NET MVC Authorize interacts with ASP.NET Forms Authorization
Preventing Open Redirection Attacks in ASP.NET MVC
The second post indicates one good reason why need to be careful with ReturnUrl - users can tamper with them.
In the example you showed above, I'd expect that, after authorization, the user would be redirected to the Forum / Index action, which would then be reading the values. If you are creating the ReturnUrl, you should be URL Encoding the second &.
Not sure on the exact reason the values don't get bound, but the easy workaround is to add those properties to your login model and add hidden fields on the form.
Try changing the decoration:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Try(LoginModel model, string ReturnUrl, string theme)
{
//read all query string param values...but how?
//I am not getting anything in string ReturnUrl, string theme. They are null
}

Resources