DropDownListFor loses list binding in validation - asp.net-mvc-3

I am using fluentvalidation and mvc3. I have a drop down list, and it works well. I wanted to test my validation and it works EXCEPT that on validation the drop down list is empty??
What I mean is that if I purposely submit while the default SelectListItem Please Select...with a value of zero is chosen then the submit fails validation and the message shows etc. but my dropdownlist is now empty??
My controller code populating the list:
if (extforum.Count > 0)
{
foreach (var s in extforum)
model.ExternalSubscription.AvailableForums.Add(new SelectListItem(){ Text = s.ForumName, Value = s.Id.ToString() });
}
else
model.ExternalSubscription.AvailableForums.Add(new SelectListItem() { Text = "None Available", Value = "0" });
//add default value
model.ExternalSubscription.AvailableForums.Add(new SelectListItem() { Text="Please Select", Value="0", Selected=true });
My razor code:
<tr>
<td>
#Html.LabelFor(model => model.ForumName):
</td>
<td>
#Html.DropDownListFor(model => model.SelectedExtBoardId, Model.AvailableForums)
#Html.RequiredHint()
#Html.ValidationMessageFor(model => model.ExtForumBoardId)
</td>
</tr>
My validator code:
RuleFor(x => x.ExtForumBoardId)
.NotEqual(0).WithMessage("Blah"));

In your HttpPost controller action you must populate the AvailableForums collection property on your view model the same way you did in your Get action that rendered the form. This is necessary if you intend to redisplay the same view containing the dropdown. This often happens in the case of a validation error. Don't forget that when you submit a form, only the selected value of the dropdown is sent to the server. The collection of all possible values is something that you need to retrieve from your backend if you intend to redisplay the same view.

Related

Html.BeginForm and Kendo Ui in MVC 4

So what I have is a form created with the beginform extension like this
using (Html.BeginForm("SendEmail", "Email", FormMethod.Post, new { id = "emailForm",
onsubmit = "return Check();"})){
inside I created some Kendo Ui widget like this
<table>
<tr>
<td>#Html.LabelFor(x => x.Senders)</td>
<td>
#(Html.Kendo().DropDownList()
.Name("Sender")
.DataTextField("Text")
.DataValueField("Value")
.BindTo(Model.Senders))
</td>
</tr>
<tr>
<td>#Html.Raw(Server.HtmlDecode(#Model.RecipientTable))</td>
</tr>
<tr>
<td colspan ="2">
#(Html.Kendo().MultiSelect()
.Name("Users")
.DataTextField("Name")
.DataValueField("Id")
.Placeholder("Optional - Choose additional users to send emails to:")
.ItemTemplate("#=LastName #, #=FirstName # #=MiddleInitial #")
.TagTemplate("#=LastName #, #=FirstName # #=MiddleInitial #")
.BindTo(Model.OptionalUsers))
</td>
</tr>
in my controller Email I have this method
[HttpPost]
public bool SendEmail(EmailModel Email){ .. stuff....}
Where the EmailModel is tightly bind to the view that contains the form from above. The question and trouble I am having is that is it possible and if so how, to have the model passed to the method containing information about what the user chose? Or is it that I can not use the form's submit and will have to manually get the value and pass it as a JSON to the controller via custom function that does a ajax call?
I thought I read that you weren't using post. The only items that are returned automatically through the post are fields that have been put in a for helper. What we do is
#Html.DropDownListFor(x => x.Sender, new { #class = "ddlSender" })
then in the script we initialize the kendo part of it
$('.ddlSender').kendoDropDownList();
this way the model item is put in a for helper so it gets posted back to the controller and you get the benefits of the kendo dropdown. Hope this helps

unobtrusive validation RANGE does not work

I am doing an MVC 3 application. I have a model with [Range(1, 175, ErrorMessage="Invalid")].
On one of the controllers the view renders perfectly with all markup for validation. On a second Controller with the same setup the Range validation which is done on a dropdownlist, does not appear on the html markup. I have validation and unostrusiveValidation true on config.web. I am using LINQTOSQL and I have done a partial class to add the additional metadata. The field does pick up the [Display(Name="State")], but the Range is not.
<tr>
<td>#Html.LabelFor(x => x.carta.INVprovincia)</td>
<td>#Html.DropDownListFor(x => x.carta.INVprovincia, Model.provinciaItems, new { #class = "ddlsmall" }) <br /> #Html.ValidationMessageFor(x => x.carta.INVprovincia)</td>
</tr>
<tr>
<td>#Html.LabelFor(x => x.carta.INVmunicipio)</td>
<td>#Html.DropDownListFor(x => x.carta.INVmunicipio, Model.municipiosItems, new { #class = "ddlsmall" }) <br /> #Html.ValidationMessageFor(x => x.carta.INVmunicipio)</td>
</tr>
The Html.XXX helpers won't generate HTML5 data-* attributes used by the unobtrusive validation framework if they are not inside a form which seems to be your case. I guess that the form is contained within a parent view. This bug (IMHO) is fixed in ASP.NET MVC 4. A possible workaround is to put the following on the to of your partial view to fake a form and make the helpers believe that they are inside a form:
#{
ViewContext.FormContext = new FormContext();
}

Validation of DropDownListFor is not working in MVC3?

Validation is Working on Other Input type text element but not working on DropDownListFor
Class Purchase Input Property Code
[Required]
public string LedgerId { get; set; }
Class View Model Code
PurchaseViewModel purchaseVM = new PurchaseViewModel
{
// PurchaseInput=purchaseInput,
Ledger = uw.LedgerRepository.Get().Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.LedgerName }),
};
View
<div class="column">
<div class="labelField">
#Html.LabelFor(model => model.PurchaseInput.LedgerId, "Party")
</div>
<div class="ItemField">
#Html.DropDownListFor(model => model.PurchaseInput.LedgerId, new SelectList(Model.Ledger, "Value", "Text"))
#Html.ValidationMessageFor(model => model.PurchaseInput.LedgerId)
</div>
</div>
On the face of it, it seems that you do not have an empty item in your select list. The validation will only trigger if the user selects a dropdown item with string length of zero. If you examine the Html source can you see the validation attributes on the dropdown ( depending on whether you are using unobtrusive validation or not)?
Yes, there are problems with validation of DropDownListFor. look at this link. They get validation data manually from metadata - http://forums.asp.net/t/1649193.aspx
Although this is a workaround, at least it fires some sort of validation. Try:
#Html.DropDownListFor(model => model.PurchaseInput.LedgerId, new SelectList(Model.Ledger, "Value", "Text"), new { #class = "required" })

MVC3 #Html.DropDownListFor not populating selected item

I have the following dropdown list in an MVC3 application and the selected item is not showing a value. My dropdown list is contained in a list of a custom class. My view code is as follows.
...
for (int i = 0; i < Model.PartAttributes.Count; i++)
{
if (Model.PartAttributes[i].IsActive)
{
<div class="row inline-inputs">
<label class="span5">#Model.PartAttributes[i].DisplayName:</label>
#Html.DropDownListFor(m => m.PartAttributes[i].Value, Model.PartAttributes[i].PartList, "Choose Part")
#Html.TextBoxFor(model => Model.PartAttributes[i].Value, new { #class = "mini" })
#Html.ValidationMessageFor(model => Model.PartAttributes[i].Value)
#Html.HiddenFor(model => model.PartAttributes[i].AttributeName)
</div>
}
}
...
The text box under the dropdown box fills correctly and the list options fill correctly. And the selected option is in the list of options to pick. What can I be doing wrong?
Try like that:
#Html.DropDownListFor(
m => m.PartAttributes[i].Value,
new SelectList(
Model.PartAttributes[i].PartList,
"Value",
"Text",
Model.PartAttributes[i].Value
),
"Choose Part"
)
AFAIK the DropDownListFor helper is unable to determine the selected value from the lambda expression that is passed as first argument if this lambda expression represents complex nested properties with collections. Works with simple properties though: m => m.FooBar. I know that it kinda sucks, but hopefully this will be fixed in future versions.

MVC equilvelant of repeater with multiple form elements and checkbox to select

I need to replicate the functionality you get with an asp repeater that contains checkboxes, textboxes, and the occasional dropdownlist in an MVC application. Om traditional webforms you get a postback event and its pretty easy to get at all the controls and their values associated with the checkbox (id).
Anybody have any good suggestions on how to get the values back on a post for the items that have the checkbox checked. I am able to get some arrays back in the FormCollection (and even a strongly typed view) but I have not been able to figure out a good way to link the values effectivly.
All rows have a checkbox and a textbox, some rows also have a dropdownlist
To further explain...
row 1 has a checkbox and a textbox
row 2 has a checkbox a textbox, and a dropdown list.
if the user selects row 1 and 2, I need to get the values for all the form elements (for some calculations). Also, I haven't come up with a good method of handling validation errors.
any suggestions are greatly appreciated.
The simplest thing to do would be to iterate the collection for which you would have a repeater for. Using Razor syntax:
#using (Html.BeginForm()) {
<table>
#for (var i = 0; i < Models.Items.Count; i++) {
<tr>
<td>
#Html.CheckBoxFor(x => Model.Items[i].SomeBool)
</td>
<td>
#Html.TextBoxFor(x => Model.Items[i].SomeString)
</td>
</tr>
}
</table>
<button type="submit">Go</button>
}
Then a controller method:
[HttpPost]
public ActionResult Index(MyViewModel viewModel) {
// view model will be bound to values in form
}
Assuming the the Model in the view is of type MyViewModel. Once you have a sense of how this works you can look into ASP.NET MVC grid frameworks.

Resources