mvc2 - getting the URL to reflect the form submission - asp.net-mvc-2

I have an MVC2 application with a form (like ya do). The user enters a query into the form (in the /Cars/Index view) and hits the "submit" button which posts to the Details action of CarsController - the Details view renders with results, and all is well and good.
The user can enter a URL (such as /Cars/Details/123-125) and they get the Details view with 123, 124 and 125 displayed, same as if you'd entered it on the form. Also well and good.
What I want to enable, if possible, is that when the user enters "123-125" or whatever in the form the URL also reflects the results - instead of "/Cars/Details" for a URL, which is what shows now, I want it to show "/Cars/Details/123-125".
For the life of me, I cannot figure out how this should be done.
Any assistance is appreciated.

Change your form to a GET instead of POST method (POST is the default), and it should just work.
<% using (Html.BeginForm("Action", "Controller", FormMethod.Get)) { %>

It sounds like its not finding a matching route definition for /Cars/Details/123-125. I think this could be happening because of the way the routing engine works.
ASP.NET MVC Route Contraints with {ID}-{Slug} Format

Ok, here is the answer I came up with:
In short: Redirect to GET
Basically, I write an action with [HttpPost] Attribute that redirects the form submittal to another action with [HttpGet] attribute. The route works whether you submit the form or type in the URL manually.
[HttpPost]
public ActionResult Details(CarViewModel model, int? pageNbr) {
// simply takes the form POST and re-routes it as a GET to pretty up the URL
// (see second Details action)
int page = pageNbr ?? 0;
return RedirectToAction("Details", new { query = model.Query, pageNbr = page });
}
[HttpGet]
public ActionResult Details(CarViewModel model, int pageNbr)
{
// various magic to create the view...
return View(avm);
}
As an added bonus, this takes care of the "Are you sure you want to resubmit?" annoyance when someone refreshes the page or hits the BACK button in their browser.

Related

Multiple forms in ASP.NET Core Razor Page, one in a modal

I am using the new ASP.NET Core Razor Pages. I have a standard login form on the page; works fine. I want to add a second form in a modal dialog on the page (forgot my password). When the user submits the modal form, I want to manually submit the form and show a message on the modal (the user then clicks close on the modal). Maybe I can't do a standard form, but was hoping to somehow leverage all the model binding and validation that comes in a Razor Page.
Any ideas on how to set up the form in the modal, submit the "forgot my password" request to the server, then display a message in the modal?
I use ajax for that case
$.getJSON("/Contact?handler=CreateNewsLetters", {"email" : email })
.done(function(data, textStatus, jqXHR) {
let modal = $("#modalFinish");
let paError = '<p>Done! <p>';
modal.find(".modal-body").html(paError);
modal.modal("show");
});
Contact.cshtml.cs
public ActionResult OnGetCreateNewsLetters(string email)
{ return new JsonResult(email); }

Can we just let "prepareFromRequest" to behave just like traditional non-Ajax page?

Ok, let see how traditional non-Ajax page work. Suppose you have a page like the below link
abc.com#!search;item=car
In the traditional non-Ajax website, when first time you call "abc.com#!search;item=car", it will go to server and get data. After that you go to other page like "abc.com#!customer;name=tom" and then you hit back button it will go back to "abc.com#!search;item=car". However, this time it won't call to the server again cos it remembered it did before.
Now Here is the GWTP problem. Suppose the above abc.com was built in GWTP technology.
At the first time wen user enters the "abc.com#!search;item=car", the GWTP app will initialize the page "search" via onBind, then the prepareFromRequest will be called & it will go to server to get data.
That is Good, no problem. However, if we open a new page (like customer page) by using revealPlace, then we hit the back button it will go back to "search" page & it will call prepareFromRequest again. The prepareFromRequest will then make the exactly same call to server again. That is not good cos it wastes resource.
So I want the "prepareFromRequest" to be called ONLY at the time we initialise the page (run after onBind) & block the "prepareFromRequest" in all other page request (ex like user press the back button).
It mean "prepareFromRequest" should work just like traditional non-Ajax page mentioned above.
Can we do that? or
Do you have a better solution?
Why don't you just check in your prepareFromRequest method if you have already a search result for that specific searchterm and only issue a call to the backend if it has changed?
Something like this:
public Presenter extends .... {
String searchItem = null;
List<DTO> searchResult = null;
#Override
public void prepareFromRequest(PlaceRequest placeRequest) {
super.prepareFromRequest(placeRequest);
String item = placeRequest.getParameter("item",null));
if (searchItem == null || !searchItem.equals(item)) {
searchItem = item;
// MAKE A CALL TO THE BACKEND AND STORE THE DATA IN A FIELD.
searchResult = GET_FROM_SERVER(searchItem);
}
}
}

Facebook tab, finding if liked

I have the following code to check if my tab is liked by the user:
protected bool IsPageLiked()
{
try
{
var current = ConfigurationManager.GetSection("facebookSettings")
as IFacebookApplication;
dynamic data = FacebookWebContext.Current.SignedRequest.Data;
if (data.page != null)
{
var pageId = (String)data.page.id;
var isUserAdmin = (Boolean)data.page.admin;
var userLikesPage = (Boolean)data.page.liked;
if (userLikesPage)
return true;
}
}
catch (Exception ex)
{
return false;
}
return false;
}
This works correctly when I load my tab initially.
However, if I try and call the same code after changing page within the tab, I get the following error:
{"Precondition failed: !String.IsNullOrEmpty(signedRequestValue)"}
Is there a way I can make this code work after the first page?
I know I can check if the tab is liked on the first page, and put this into a session object or something, but I'd prefer not to do this.
My app itself is MVC 3
Thanks
EDIT
I think what is happening is when I change page (I'm using a RedirectToAction method), it's loosing the signed_request query string, hence the error I am getting.
Edit 2
Not sure the above is what is happening after all, as I can't see any query string values on the initial page? It's still not able to get the signedrequest.
It looks like the signed_request is a form object (Request.Form["signed_request"] returns the string in the inital page, but not the second page).
Page tabs are basically just your app within an iframe on the page, like you've noticed the signed request is POSTED to the tab on page load.
When you change page within the tab the outer Facebook frame isn't reloading so the signed_request is not being re-posted to your tab which is why you can't access it again.
You will need to either pass the signed_request from one page to the next yourself or make sure all links use target="_top" so that the whole page is reloaded each time and you still get the POST.
To define which page you want your tab to load you can use an additional parameter called app_data in the url to your tab, eg
http://www.facebook.com/MY_PAGE?sk=app_MY_APP_ID&app_data=A_STRING_OF_DATA
Your tab will then receive this as part of signed_request, you can grab it and use it to work out which page your tab needs to display.

hyperlinks with gwt

I am new to GWT, I would like to use hyperlinks where I would like to redirect the user to another form.
My question is that , creating hyperlinks are easy, but how do I use them ?? addClickListener seems to be deprecated, is there any other way to go around this ?
Update 1
I have implemented the Hyper link code as follows :
Hyperlink link0 = new Hyperlink("Show Boxes","showbox");
History.addValueChangeHandler(this);
History.fireCurrentHistoryState();
public void onValueChange(ValueChangeEvent<String> event) {
String eventValue=event.getValue();
if(eventValue.equals("showbox")){
showBox();
}
}
With this I see that the form corresponding to one hyperlink is visible, but this form is not closed and another for is not being opened when I click one another hyperlink.
I am using DockPanel to display the form in the East direction. The forms for all the hyperlinks are just being displayed one below the other.
Any comments/suggestions for the same ?
Thanks,
Bhavya
Use the Anchor.addClickHandler() method!
Anchor a = new Anchor("text");
a.addClickHandler(new ClickHandler(){
// etc
});
If the another form is within your GWT application, then you should consider using Hyperlink. In constructor you provide a history token which is pushed to History object when link is clicked. You just need to handle event that a history token has changed. It decouples navigation events from your logic. This will also make your application aware of back-forward and allows users save bookmarks to specific state (form in your case). Anchor is intended more for external links.
See it described in Coding Basics - History .
First you need to create a HyperLink with a history token:
Hyperlink link = new Hyperlink("link to foo", "foo");
In above example, "foo" is the history token.
Then you should register your value change handler on History object, like
History.addValueChangeHandler(myValueChangeHandler);
In your value change handler, you will need to read in the current token using event.getValue().
class MyValueChangeHandler implements ValueChangeHandler<String>() {
public void onValueChange(ValueChangeEvent<String> event) {
//get the new value of history token
//clicking on above example link will return "foo" here
String historyToken = event.getValue();
}
}
What does the value of history token means is up to your application to decide. For example you can maintain a simple Map between history tokens and the view that should be rendered. In more sophisticated applications you can encode more details into the token -- like initial state of the form that should be displayed.

Detect Browser Refresh vs. Form Submit in ASP.Net MVC 2

I have an ASP.Net questionnaire application that resubmits data to the same page, showing a different question each time. There are BACK and NEXT buttons to navigate between questions.
I would like to detect when the form is submitted due to a browser refresh vs. one of the buttons being pressed. I came across a WebForms approach but don't know how to apply those principals in an MVC 2 application since page events aren't available (as far as I know... I'm pretty new to Microsoft's MVC model).
How would one apply that principle to MVC 2? Is there a better way to detect refresh?
You could use the redirect-after-post pattern with TempData. Example:
The Back and Next buttons POST a form to a controller action
The controller action puts some state into the TempData and redirects to another controller action which will verify that the data is in TempData and return the view
The user presses F5 on the browser, the previous action is called on GET and as the state is no longer into TempData you know the user pressed F5 and didn't pass through the form submission.
And to illustrate this:
public class HomeController: Controller
{
public ActionResult Index()
{
var state = TempData["state"];
if (state == null)
{
// the user directly arrived on this action without passing
// through the form submission
}
return View();
}
[HttpPost]
public ActionResult Index(string back)
{
TempData["state"] = new object();
return RedirectToAction("Index");
}
}