Multiple instance of partial razor form - asp.net-mvc

I have 2 nested partial controls
User Control1:
Html.BeginRouteForm
(
Html.RenderPartial (path of child form)
)
ChildControl:
Html.LabelFor(x=>x.FirstName,"First Name")
Html.TextBoxFor(x=>x.FirstName)
...
Problem:
I have 2 instance of this partial control on home page. When I click on Submit button of second instance, form is posted using AJAX & JQuery. Since FirstName has a required constraint, form renders back with required validation triggered for FirstName. Here comes the issue: When I click on label "First Name", cursor gets focused on First Name TextBox of first instance of partial form instead of second instance where validation triggered.
Any suggestion on how to tackle this?
Thanks a lot!

At a guess, I'd say you're the victim of a duplicate ID, because the two instances of ChildControl are likely generating the same ID string.
Unlike ASPNET, MVC appears to generate IDs "locally". In other words, nothing behind the scenes keeps track of how many "controls" are generated, which is what allows ASPNET to generate unique ids.
If so, it's an easy enough problem to solve. Just add your own ID to each instance of ChildControl, doing something like the following:
#Html.TextBox("rel_date", Model.Value.rel_date.ToSiteString(), new { #class = "date-picker", style = "width: 75px;", id = "" })
Here I'm actually suppressing the ID on a textbox I'm generating by passing in an empty ID value in the html attributes parameter of the TextBox helper call. You'd insert some ID which you know to be unique to the page.
BTW, you can quickly check to see if I'm right about the duplicate IDs by checking the generated html for the page. When it's up in IE just hit F12 (in IE9 anyway). That'll open a window which allows you to browse the html that's generating your page. You can read it to see if the ID attributes of the two textboxes are the same, which would support my theory.
Good luck!

Related

Why are my dotnet 5.0 mvc form fields retaining their input values on post?

I have an dot net 5.0 mvc page which takes a model object (ClassFoo) which when constructed generates an instance of (classBar). ClassBar has various properties (FieldA, FieldB, FieldC) all are strings.
The Views content is all in a form and the form's input fields are all from ClassFoo.ClassBar's various properties. Initially, when the page is accessed, all form input values are empty. However when I put data into them and then submit the form, the form values are still there when the page loads. However I don't understand why this is because I'm explicitly creating a new model during the controller operation but I am not actually populating the Model.ClassBar with the content from the post before I return model to the View for generation.
What I would expect is that all of the form fields would be empty however that is not the case. I know if asp.net the form values are stored and restored automatically but I didn't think that happened in mvc.
After looking into ModelState recommended by Nick Albrech in the comments I reviewed the hint associated w/ the HtmlHelper.TextBoxFor() which states the following:
... Adds a "value" attribute to the element containing the first non-null value found in: the ActionContext.ModelState entry with full name, or the expression evaluated against ViewDataDictionary.Model. See [IHtmlHelper.NameFor] for more information about a "full name".
So effectively what's happening is similar to what I thought asp.net mvc wasn't doing in that it populates the ModelState from a get/post request with the name and values of the form being submitted. Then based on the use of these helper functions (and also asp-for attributes used in razor views views), it either provides values from the saved model state form values OR the model passed to the view. Note: this does not seem to work if you set the value of an input element = #Model.[someProperty]
The take away from this is that you do not necessarily need to update your model object with content from the previous form submit in order to have the page populate the form contents back to the screen. Allow asp.net mvc to do the manual tasks by making use of these razor helpers.
Shoutout to Nick for the assist on this one. A solid member of the stackOverflow community.

Adding / Removing MVC typed partial view to form on mouse click

first question on stack so please be gentle ;). I have a long MVC form that requires the user to be able to click an 'Add Person' button , which would then create a copy of an 'Add Person' partial view , which is then filled in with the Person details. On form submit, the controller would then need to contain the details of each new added person stored as a Person object in the Person[] array I have in my View Model. so for example:
User clicks 'Add Person' button 3 times
3x ' Add Person' partial views are displayed on screen, one after the other
User fills in the 3 listed forms
User submits form
Model submitted to controller contains an array of 3 Person objects, populated with the values the user has entered.
I've got the EditorFor working when displaying a list of template forms for an already populated Array of Person objects, but not sure how I would go about actually inserting a new 'Person' into the model via mouse click. Each new person will need to be given an ID of Guid type.
Sorry if my question is vague.I'm trying not to be. I cant provide sample code for my exact solution as this is for a government project but can whip up an similar example if required. Thank you for your time
This should give you a general idea of how to do it
var partialView = '#Html.Raw(#Html.Partial("Person", new ViewModel()).ToString().Replace("\r\n", String.Empty).Replace("\n", String.Empty).Replace("\r", String.Empty))';
partialView = partialView.replace('id="1"', 'id=ListName_{0}'.format(newId));
$("#persons").append(partialView);
Firstly I create a variable containing the partial view as a string, next we need to change the ids and the rest of the properties so they follow the convention used for lists when data binding in MVC.
It follows the following convention
<input type="text" name="stocks[0].Key" value="MSFT" />
<input type="text" name="stocks[1].Key" value="AAPL" />
See the following for a description
http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx
Once all ids are correctly created you can post the form as per usual.
You're not going to be able to add a person to the view model from client side code. The view model doesn't exist client side, only server side.
My suggestion is to make sure the partial views are all in the form being submitted and have an array of Person objects as a parameter in the controller action you're posting to. You'll need to make sure you use the correct convention for each name on each input field of each partial view.
So for example the partial view each input field would need to be named like this Person[index].Field. Where index is an integer and Field is the appropriate property from the Person model that this particular input tag represents.

How to preserve text during a postback with ASP.NET MVC 3

I have a Product edit screen. The user can select a Vendor for the Product. To do this, I display a jQueryUI dialog box which allows them to browse for and select a Vendor. When the user selects the Vendor, I update a hidden VendorID input on the page, which is part of my page's model. I also update several divs with details about the Vendor they have selected. These are for display purposes only--only the id is needed to persist the selected Vendor.
This all works fine and dandy except when there is an error on postback, in which case I redisplay the same view. ModelState takes care of preserving all my form fields (including the hidden VendorID). However, my divs with the Vendor text are (of course) empty since they're not posted to the server.
I first went down the path of creating hidden fields for each of my Vendor display fields and putting them on the model. Then the hidden fields survive the postback, but that doesn't solve the problem of actually redisplaying the text on the screen.
The three options I can think of are:
On postback, if there is an error, go to the database, fetch the Vendor using the supplied VendorID and re-populate the model with the text I want to display.
Use RenderAction and have an action which renders the details of the selected Vendor.
Use readonly textboxes instead of divs to display the Vendor details.
None of these feel very satisfactory to me. I feel like I might be missing an obvious solution. Are there any better solutions?
I would suggest you not have the extra Vendor information come down as part of the main page. Create a javascript function showVendorInfo(). When called, if the VendorID hidden input has a value, it gets the relevant Vendor information via AJAX and displays it, using an AjaxGetVendorInfo action method. Call this function from two places:
In document.ready()
after a Vendor is selected with jQueryUI display.
Now, this would be in an action method. You could, if you expect your users to have latency issues, do the following to avoid some ajax calls: In the view check if you know the VendorID; if so, call Html.RenderAction call the same AjaxGetVendorInfo action method from the view.
A bonus to this is that it avoids what I have found to be a big no-no: Including both display-only values and model-binding values in your ViewModel. This makes for a very confusing ViewModel, especially when there are validation errors. [Getting on soap box] It's best to have your ViewModel to just have properties intended for modelbinding, for your state. Put list values, extra display information, etc., into ViewData or have them show up via AJAX.

ASP.NET MVC3 Client side validation

I am building a search form for my web application using MVC3. My form is basically divided in two sections.
1st Section has 3 search criteria. First Name, Last Name and Zip code and beneath that section there is a "Search" button which I can click and it should do a client side validation and give me an error message if any of the fields are blank.
2nd section on the same page has just one textbox - to search by "Quote Number". So that section has one textbox to enter quote number and beneath there is another button called "Search". When I click on this search button it should only validate that the Quote Number field is not empty.
I have a viewmodel which has all 4 properties (FName,LName,Zip,Quote Number) and I am binding that on the page. Both the button will post back the page (I know that there is a way to identify which button was clicked on postback). The problem I am facing is on postback everything is posting back and if I use datannotations to do RequiredField check, it does validation on all the 4 fields but I should check for which button is clicked and based on that only fire validation on either 3 fields or only on 1 fields. How do I achieve this functionality? I hope I clearly explained the issue.
Thanks
Since this is MVC, don't think of these as postbacks, think of them as submits. As they are searching by different criteria, they should really be two different forms submitting to two different actions. As they are separate actions, each can have it's own view with it's own ViewModel and validation. Then to combine them into one physical page to present to the user just use partial rendering to put them both into the same view.
Basically the view you present to the user would have something like:
#{
Html.RenderAction("SearchByName");
}
<!-- maybe some markup to visually separate them -->
#{
Html.RenderAction("SearchByQuote");
}
Also gives you the added benefit of having each action be responsible for a single task and you don't have to put in code to figure out which button was clicked, etc.
And just in case you think to yourself "Hey, since both are search, just with different number of parameters, can't I overload the Search action?" No.
Kevin,
Change your page so that you have two different forms, one for each search type. When you click submit in one form, only that form's child fields will be validated.
Then, as R0MANARMY suggested, have two separate actions, one for each search form.
counsellorben

Mapping individual buttons on ASP.NET MVC View to controller actions

I have an application where I need the user to be able to update or delete rows of data from the database. The rows are displayed to the user using a foreach loop in the .aspx file of my view. Each row will have two text fields (txtName, txtDesc), an update button, and a delete button. What I'm not sure of, is how do I have the update button send the message to the controller for which row to update? I can see a couple way of doing this:
Put each row within it's own form tag, then when the update button is clicked, it will submit the values for that row only (there will also be a hidden field with the rowId) and the controller class would take all the post values as parameters to the Update method on the controller.
Somehow, have the button be scripted in a way to send back only the values for that row with a POST to the controller.
Is there a way of doing this? One thing I am concerned about is if each row has different names for it's controls assigned by ASP.NET (txtName1, txtDesc1, txtName2, txtDesc2), then how will their values get mapped to the correct parameters of the Controller method?
You can use multiple forms, and set the action on the form to be like this:
<form method="post" action="/YourController/YourAction/<%=rowId%>">
So you will have YourController/YourAction/1, YourController/YourAction/2 and so on.
There is no need to give different names to the different textboxes, just call them txtName, txtDesc etc (or even better, get rid of those txt prefixes). Since they are in different forms, they won't mix up.
Then on the action you do something like
public ActionResult YourAction(int id, string username, string description)
Where username, description are the same names that you used on the form controls (so they are mapped automatically). The id parameter will be automatically mapped to the number you put on the form action.
You can also have multiple "valid-named" buttons on the form like:
<input type="submit" value="Save" name="btnSave" id="btnSave"/>
<input type="submit" value="Delete" name="btnDelete" id="btnDelete" /
and than check to see what submit you have received. There can be only one submit action sent per form, so it is like all the other submit buttons did not actually existed in the first place:
if ( HttpContext.Request.Form["btnDelete"] != null ) {
//Delete stuff
} elseif ( HttpContext.Request.Form["btnSave"] != null ) {
//Update stuff
}
I also think that you can implement a custom ActionMethodSelectorAttribute like here http://weblogs.asp.net/dfindley/archive/2009/05/31/asp-net-mvc-multiple-buttons-in-the-same-form.aspx (also listed above) to have cleaner separated code.
As rodbv said you want to use seperate <form> elements.
When you are using Asp.Net MVC or classic html (php, classic asp, etc) you have to forget the Asp.Net way of handling button presses. When a form is posted back to the webserver all the server knows about is simply "the form was sent, and contained the following input elements".
Asp.net (standard) adds a wrapper round many of the standard html postback actions using javascript (the __doPostback javascript function is used almost everywhere) and this adds information about which input element of the form caused the postback and delivers it to the server in a hidden form variable. You could mimic this behavior if you really so desired, but I would recomend against it.
It may seem strange 'littering' a page with many <form>'s, however it will mean that the postback to the server will be lighter weight and should make everything run that little bit faster for the user.

Resources