MVC3 ModelState fails after changing to using a ViewModel - asp.net-mvc-3

I've changed my controller to pass a VoucherBatchViewModel instead of a VoucherBatch
[HttpPost]
public ActionResult Edit(Guid id, VoucherBatchViewModel voucherBatchViewModel)
{
if (!ModelState.IsValid)
{
SetupDropDowns();
And the vm:
public class VoucherBatchViewModel
{
public VoucherBatch VoucherBatchInVM { get; set; }
public string CreationReference { get; set; }
public int NumberToMove { get; set; }
public int VoucherCodeLength { get; set; }
}
Question: Why is my ModelState invalid? The drop down has not populated the correct field in the ViewModel. The html does produce the correct
<div class="editor-field">
#Html.DropDownList("VoucherProviderId",
new SelectList(ViewBag.VoucherProviders as System.Collections.IEnumerable,
"Id", "Name", Model.VoucherBatchInVM.VoucherProviderId))
and Edit get contains this which I use to populate the DropDown.
ViewBag.VoucherProviders = uow.VoucherProviders.OrderBy(v => v.Name).ToList();
Html:
<select id="VoucherProviderId" name="VoucherProviderId"><option value="0469f9ba-c4ea-401a-86f1-095208c6a7fb">Name</option>
<option selected="selected" value="e0aeed44-3574-46f1-a493-0a6a87948942">Voucher Provider 1</option>
<option value="5abe1158-282b-4330-9b11-01de503a2f16">Voucher Provider 2</option>

Can't see any VoucherProviderId property in your VoucherBatchViewModel. So your HTML is not valid. It should be:
<select id="VoucherProviderId" name="VoucherBatchInVM.VoucherProviderId">
...
</select>
And to achieve this markup you I would recommend you using strongly typed helpers:
#Html.DropDownListFor(
x => x.VoucherBatchInVM.VoucherProviderId,
new SelectList(ViewBag.VoucherProviders as System.Collections.IEnumerable, "Id", "Name")
)
And please replace this ViewBag which is making me vomit with a strongly typed model property:
#Html.DropDownListFor(
x => x.VoucherBatchInVM.VoucherProviderId,
new SelectList(Model.VoucherProviders, "Id", "Name")
)

Related

ASP.Net MVC 6 PartialView model binding confusion

Background
We need to submit model with items. For that purpose, we make this complex model:
public class PaymentViewModel
{
public decimal? Payment { get; set; }
public string Description { get; set; }
public List<SplittedPaymentViewModel> SplittedPayment { get; set; } = new List<SplittedPaymentViewModel>();
}
public class SplittedPaymentViewModel
{
public short SplittedPaymentId { get; set; }
public decimal? Payment { get; set; }
public string Description { get; set; }
}
For rendering html, we this two views, one regular: CreatePayment
#model ZevApp.ViewModels.Record.PaymentViewModel
...
<input class="form-control" asp-for="Payment" type="number" />
<input class="form-control" asp-for="Description" />
...
<div class="panel-body" id="SplittedPayments">
#foreach (var spItem in Model.SplittedPayment)
{
#Html.Partial("SplittedPaymentPartial", spItem);
}
...
</div>
And the other Partial: SplittedPaymentPartial
#model ZevApp.ViewModels.Record.SplittedPaymentViewModel
...
<input class="form-control" asp-for="Payment" type="number" />
<input class="form-control" asp-for="Description" />
...
As you can see, from the first view, we call partial view and pass them item by item form the SplittedPayment list.
Unexpectedly behavior
We run the code but unexpectedly behavior is occur:
Each partial view bind Payment and Description form parent PaymentViewModel, not from a passed item?
Does anybody know what is wrong?
Each view define model at the beginning of the file.
From the controller we return PaymentViewModel, and for a test, there are tree SplittedPaymentViewModels. But we can't see values from the items.
I found that problem was CreatePayment.cshtml (thanks to the people from MVC community). It doesn't provide any information about the spItem expression when invoking the partial view.
var savePrefix = ViewData.TemplateInfo.HtmlFieldPrefix;
for (var i = 0; i < Model.SplittedPayment.Count; i++)
{
ViewData.TemplateInfo.HtmlFieldPrefix = Html.NameFor(m => m.SplittedPayment[i]);
var spItem = Model.SplittedPayment[i];
#Html.Partial("SplittedPaymentPartial", spItem);
ViewData.TemplateInfo.HtmlFieldPrefix = savePrefix;
}
You can find full description on https://github.com/aspnet/Mvc/issues/4106

Generating a selected attribute with DropDownListFor (not DropDownList), by using strongly type model with SelectList

I've tried to populate a dropdownlist with a viewModel passed from a controller with the main goal of setting a selected attribute tag, so that when the dropDown-list loads a specific item in the dropdown-list is selected. I'm using MVC 5 with Razor.
There are many question related to DropDownListFor but unfortunately I haven't found what I'm looking for.
I've found many solutions that work with viewbags, but I this is not
what I'm looking for, I want to populate the dropdown-list through a
strongly typed model.
The Html helper I want to use is #Html.DropDownListFor (not #Html.DropDownList). From what I know helpers postfixed with For are overloaded with linq expressions, they are used to deal with models and are strongly typed, while the non postfixed For are used with viewbags.
This is what it should look like, the default city selected should be "Monza"
At the moment I've managed to achieve this result only with #Html.DropDownList, as said before this is not my intention I want to achieve the same result with #Html.DropDownListFor. For the sake of documentation this is the code:
This approach uses #Html.DropDownList
MODEL
public class City
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CityId { get; set; }
public int ProvinceId { get; set; }
[Display(Name = "Città")]
public string Name { get; set; }
[Display(Name = "CAP")]
public string ZipCode { get; set; }
public int Dispose { get; set; }
public virtual Province Province { get; set; }
}
VIEW MODEL
public class AccountIndexGetVM
{
public UserData userData = new UserData();
public AddressUser addressUser = new AddressUser();
public IEnumerable<SelectListItem> cities { get; set; } //<--Cities to DDL
}
CONTROLLER ACTION
//Populating data to the view model and send to view
accountIndexGetVM.userData = userData;
accountIndexGetVM.addressUser = addressUser;
accountIndexGetVM.cities = new SelectList(db.Cities, "CityId", "Name", addressUser.City.CityId.ToString());
return View(accountIndexGetVM);
VIEW
creating dropdown-list in
#using MyProject.ViewModels.Account
#model AccountIndexGetVM
//some code...
<td>#Html.LabelFor(m => m.addressUser.City.Name)</td>
<td>#Html.DropDownList("CityAttributeIDVAlue", Model.cities, "Please Select a City")</td>
HTML SOURCE CODE RESULT
<td><select id="CityAttributeIDVAlue" name="CityAttributeIDVAlue"><option value="">Please Select a City</option>
<option value="277">Aosta</option>
<option value="4156">Meda</option>
<option value="4175">Melegnano</option>
<option value="4310">Milano</option>
<option selected="selected" value="4750">Monza</option> <!--Selected is PRESENT-->
</select></td>
This approach uses #Html.DropDownListFor
As you can see the default selected ddl item is not select, instead the optional ("Please select a city") is selected. This is not my intention, "Monza" should be selected when the ddl is loaded and a selected attribute should be present in the HTML option tag.
The only change I've made is in the view, this is the code, and used the DropDownListFor helper:
VIEW
<td>#Html.LabelFor(m => m.addressUser.City.Name)</td>
<td>#Html.DropDownListFor(m => m.cities, (IEnumerable<SelectListItem>)Model.cities, "Please Select a City")</td>
HTML GENERATED
<td><select id="cities" name="cities"><option value="">Please Select a City</option>
<option value="277">Aosta</option>
<option value="4156">Meda</option>
<option value="4175">Melegnano</option>
<option value="4310">Milano</option>
<option value="4750">Monza</option> <!--No selected attribute present-->
</select></td>
Question:
Is there a way to use DropDownListFor Html helper to generated a slected tag in the html ddl or the only way to go is DropDownList?
I'm not sure how Select helpers differ. I passed this list along with the view model.
List<SelectListItem> citySelectList = new List<SelectListItem>();
cityList = cities.GetAll().OrderBy(x => x.DESCRIPTION).ToList();
foreach (var city in cityList)
{
citySelectList .Add(new SelectListItem()
{
Value = city.ID,
Text = city.Desc,
Selected = true
});
}
Then on the view:
#Html.DropDownListFor(x => x.City, Model.CitySelectList, "", new { id = "citySelectID" })

How to validate textbox in MVC3 that must contain string started with characters "PR"

i am very much new to MVC3 and working with MVC3 razor application. I need to validate a textbox on View in such a way that, the textbox will accept only those strings which are starting with characters "PR" and 4th character of that string must be "2". It would be great if anybody helps me. Thanks in advance
Well you need regex. I'm not exactly sure what the regex would be and what your string contains. But if you need to have 2 matches in there, you could split it and use 2 textboxes and join the values on post.
ViewModel:
public class MyViewModel
{
[RegularExpression("^PR[A-Za-z0-9]", ErrorMessage= "Invalid Text1")]
public string MyText1 { get; set; }
[RegularExpression("^2[A-Za-z0-9]", ErrorMessage= "Invalid Text2")]
public string MyText2 { get; set; }
}
Warning, this regex may be faulty. I invite others to edit/post comments and i can update it with correct regex
View:
#model MyProject.Models.MyViewModel
#using (Html.BeginForm())
{
#Html.TextBoxFor(m => m.MyText1)
#Html.TextBoxFor(m => m.MyText2)
<button type="submit">Submit</button>
}
Hope this helps
Model
public class RegisterModel
{
public int ID { get; set; }
[RegularExpression(#"^PR[a-zA-Z0-9]2([a-zA-Z0-9]*)$", ErrorMessage = "Please enter valid Name.")]
[Required(ErrorMessage = "Name is required.")]
public string Name { get; set; }
}
View
#using (Html.BeginForm("DYmanicControllerPage", "Test", FormMethod.Post, new { id = "FrmIndex" }))
{
<div>
#Html.LabelFor(m => m.Name)
#Html.TextBoxFor(m => m.Name)
#Html.ValidationMessageFor(m => m.Name)
</div>
}

Razor view dropdown list for a model class in MVC3

I have two model class in MVC3 one for Services which have those properties
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public int ChildOf { get; set; }
It also have a DB table by Entityframework
Another model is Quata which have those properties
public int ID { get; set; }
public string Sender_Name { get; set; }
public string Description { get; set; }
.....
......
public Services Service_ID { get; set; }
It also have a DB table by Entityframework
I want to create a Razor(C#) view (for Quata) where user can send a quata by fill a html form but where i wanna show a dropdown list with Services ID as dropdown value and Services Name as dropdown text which is also come dynamically from the Services DB table .
My question is how i should create that dynamic dropdown list by #Html.DropDownListFor ? and send the selected data from that dropdown list to a Controller ?
Try this
Controller:
public ActionResult Create()
{
var Services = new Services();
Services.Load(); //load services..
ViewBag.ID = new SelectList(Services.ToList(), "Id", "Name");
return View();
}
[HttpPost]
public ActionResult Create(Quata Quata)
{
//save the data
}
A strong Typed View: (Using Razor)
#model Quata
#using (Html.BeginForm()) {
<fieldset>
<legend>Quata</legend>
<div>
#Html.LabelFor(model => model.Service_ID.ID, "Service")
</div>
<div>
#Html.DropDownList("ID", String.Empty)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
take a look at #Html.DropDownListFor
So say your viewmodel has a list of said Services.
Something that may work for you is the following (you may not need a for loop here, editor is supposed to eliminate that, but I had some weird binding issues).
In your top level view which points at your viewmodel (#model Quata, assuming Quata is your viewmodel) have this code :
#For i = 0 To Model.DropdownListInput.Count - 1
Dim iterator = i
#Html.EditorFor(Function(x) x.DropdownListInput(iterator), "EnumInput")
Next
In your Editor Template (create a subfolder under the view folder this dropdownlist will be in called editor templates and name the template whatever you desire, mine was EnumInput).
In your editor template, which should point at your model for Services (#model Services) have something like the following code (with substitutions for your appropriate variable names):
#<div class="editor-label">
#Html.LabelFor(Function(v) v.value, Model.DisplayName)
</div>
#<div class="editor-field">
#Html.DropDownListFor(Function(v) v.value, New SelectList(Model.ParamEnums, "ValueForScript", "EnumValue"), "--Please Select A Value--")
#Html.ValidationMessageFor(Function(v) v.value)
</div>
Replace the list with your list and the lambda values with yours (#Html.DropDownListFor(x => x.id, New SelectList(x.ServiceList, "ID", "Name"), "--Please Select A Value--") or something like that.
Note that this code is in VB, but it should provide a rough guide.

How to handle Dropdownlist in mvc asp .net

this is my Model1 class
namespace chetan.Models
{
public class Model1
{
public string selectedItem { get; set; }
public IEnumerable<SelectListItem> items { get; set; }
}
}
this is my controller class
public class HomeController : Controller
{
private rikuEntities rk = new rikuEntities();
public ActionResult Index()
{
var model = new Model1
{
items = new[]
{
new SelectListItem { Value = "Theory", Text = "Theory" },
new SelectListItem { Value = "Appliance", Text = "Appliance" },
new SelectListItem { Value = "Lab", Text = "Lab" }
}
}; return View(model);
}
public ActionResult viewToController(Model1 m)
{
string getSelectedName = m.selectedItem;
return Content(getSelectedName);
}
}
this is my view...
#using (Html.BeginForm("viewToController", "Home"))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>emp</legend>
<div class="editor-field">
#Html.DropDownListFor(x => x.selectedItem,
new SelectList(Model.items, "Value", "Text"))
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
i want to add a drop downlist and i want to use selected value in viewToController action of homeController. and there is also one error in View page is "an expression tree may not contain dynamic operation" in (x=>x.selectedItem). Please solve my problem .
I don't understnad what you exactly need. You want to dynamicly add items to the drop down from the database?
I'm big fan of jQuery. You can do everything what you want with HTML using jQuery. So if you are looking how to automaticly add items to the drop down, take look at this: How do I add options to a DropDownList using jQuery?

Resources