handle direct url with history api in asp.mvc - ajax

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.

Related

MVC3 url routing - render view with previous url (like a postback)

I have a Controller which has a Create method to handle HttpPost data from a form. The page containing the form is accessed by the URL
CallOutcome/Call?orderId=114565
When the form is submitted, I do a db insert & create a view model object which is returned to the view to display the form again. This works fine, however the URL has now changed to the name of my action method:
CallOutcome/Create
How can I make it show the original URL? The desired result would be like that it worked like a postback, i.e. reshowing the same page and URL.
This is my (simplified) action method, which returns a CallDetailsViewModel object to a view named 'Call':
[HttpPost]
public ActionResult Create(GGAP_CallOutcome callOutcome)
{
if (ModelState.IsValid)
{
callRepository.SaveCallOutcome(callOutcome);
return View("Call", new CallDetailsViewModel{
CustomerOrder = new CustomerOrder{},
CallOutcome = new CallOutcome{},
Task = new Task{}
});
}
}
not many responses! too close to christmas maybe?
For the record, I used RedirectToRoute:
return RedirectToRoute(new
{
controller = "CallOutcome",
action = "Call",
orderId = Convert.ToInt32(callOutcome.OrderId)
});
Which does exactly what I wanted.

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 }
)

MVC3 Recommended Controller, Action query re-use

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

Is there a simple way to pass data into an MVC3 app?

[Edit] To try to clarify:
I have a view that needs to be launched from an external application. The application requires string data to be passed from an external application (the data is free text and too long to pass as a query parameter), So I would like to launch the MVC application with a POST request. The view that is launched also needs to post data back to itself in order to submit the data it collects for storage in a database. So I end up with a View with two HttpPost flagged methods in my controller (MVC throws an error that there are ambiguous Create methods).
So in the code below Create() would be posted to from the external application. Create(FormCollection collection) would be posted to when a displayed View is submitted.
//POST: /Application/Create
[HttpPost]
public ActionResult Create()
{
MyModel model = new MyModel();
//Parse External Data to model from Request.InputStream
return View(Model);
}
//POST: /Application/Create
[HttpPost]
public ActionResult Create(FormCollection collection)
{
//Save form collection data to database
return RedirectToAction("Index");
}
So long story short, how can I post data to an MVC application to launch a view, without getting an error for an ambiguous call.
Thanks.
in the first case when the post method comes in from the outside:
return View("ConfirmCreate", model)
Then create an action method named ConfirmCreate. After ConfirmCreate is called the second time you will redirect back to Index as you have.
So I was able to do this by changing the POST call to load the application to a PUT To avoid have duplicate post endpoints), then sending the PUT from an ajax call in another application and replacing the current document with the returned html from the successful ajax call. Thanks for the suggestions.

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