I have a really simple question. I have a form where if you check the checkbox and submit the form it changes the value to true (it's false by default). At the moment it doesn't work for me. So I am asking how should I do it?
Here's a few things how I do them. There's a value "IsConfirmed"
public virtual bool IsConfirmed {get;set;}
And I have a simple HttpPost method.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "UserName,Id,Email")] ApplicationUser formuser, string id, string RoleId)
{
var role = new ApplicationUser() { Id = formuser.Id, Email = formuser.Email, IsConfirmed = formuser.IsConfirmed };
await UserManager.UpdateAsync(role);
return RedirectToAction("Index");
}
Here's my view
#model CPO.Models.ApplicationUser
#{
ViewBag.Title = "Edit";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
#Html.HiddenFor(model => model.Id)
<table class="table table-bordered table-hover">
<tr>
<th>
#Html.DisplayNameFor(model => model.Email)
</th>
<th>
#Html.DisplayNameFor(model => model.UserName)
</th>
<th>
#Html.DisplayNameFor(model => model.FirstName)
</th>
<th>
#Html.DisplayNameFor(model => model.LastName)
</th>
</tr>
<tr>
<td>
#Html.HiddenFor(model => model.Email)
#Html.DisplayFor(model => model.Email)
#Html.ValidationMessageFor(m => m.Email, "", new { #class = "text-danger" })
</td>
<td>
#Html.HiddenFor(model => model.UserName)
#Html.DisplayFor(model => model.UserName)
#Html.ValidationMessageFor(m => m.UserName, "", new { #class = "text-danger" })
</td>
<td>
#Html.HiddenFor(model => model.FirstName)
#Html.DisplayFor(model => model.FirstName)
</td>
<td>
#Html.HiddenFor(model => model.LastName)
#Html.DisplayFor(model => model.LastName)
</td>
<td>
#Html.DropDownList("RoleId", "Select Role")
</td>
<td>
#Html.EditorFor(model => model.IsConfirmed)
</td>
<td>
<input type="submit" value="Edit" class="btn btn-default"/>
</td>
</tr>
</table>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Weirdly but it doesn't work and I have no idea why, maybe I missed to define something, but the model get's it's value as false even though it is checked.
Any help is highly appreciated, If I made mistakes please be kind to write I made them in the comments and I'll fix them
You have excluded the IsConfirmed property from binding by your use of the BindAttribute
[Bind(Include = "UserName,Id,Email")]
which means only bind the values for properties UserName, Id and Email
Remove the attribute, or change it to include the property
[Bind(Include = "UserName, Id, Email, IsConfirmed")]
Note also you have excluded properties FirstName, LastName and RoleId from binding so there is little point including a form controls for them
Related
Is it possible validating textbox in this case? The value in this TextBox ( #Html.TextBoxFor(model => model.FirstSetList[i].Amount)) must be divisible by another value - Pack in this case (#Html.DisplayFor(model => model.FirstSetList[i].Pack)).
I tried to use Fluent Validation, but there is a problem with client-side validation. Maybe it can be done without fluent validation. Only with basic DataAnnotation?
Here is the code of view:
#model FP.WebUI.ViewModels.DataItemVm
<h3>
What kind of currencies you currently own?
</h3>
<br />
<div>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.FirstSetList.FirstOrDefault().Name)
</th>
<th>
#Html.DisplayNameFor(model => model.FirstSetList.FirstOrDefault().Pack)
</th>
<th>
#Html.DisplayNameFor(model => model.FirstSetList.FirstOrDefault().Amount)
</th>
</tr>
#using (Html.BeginForm())
{
for (var i = 0; i < Model.FirstSetList.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(model => model.FirstSetList[i].Name)
#Html.HiddenFor(model => model.FirstSetList[i].Name)
</td>
<td>
#Html.DisplayFor(model => model.FirstSetList[i].Pack)
#Html.HiddenFor(model => model.FirstSetList[i].Pack)
</td>
<td>
#Html.TextBoxFor(model => model.FirstSetList[i].Amount)
</td>
</tr>
}
<input type="submit" value="Confirm" class="btn btn-success" />
}
</table>
</div>
UPDATE
I was trying to use Remote Annotation, however chrome doesn't send any information to my JsonResult Method and i don't know why.
My ViewModel:
.
.
.
[Remote("Divisibility", "Account", HttpMethod = "POST", ErrorMessage = "Value is incorrect.")]
public int Amount { get; set; }
.
.
.
My View:
.
.
.
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
#using (Html.BeginForm())
{
for (var i = 0; i < Model.FirstSetList.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(model => model.FirstSetList[i].Name)
#Html.HiddenFor(model => model.FirstSetList[i].Name)
</td>
<td>
#Html.DisplayFor(model => model.FirstSetList[i].Pack)
#Html.HiddenFor(model => model.FirstSetList[i].Pack)
</td>
<td>
#Html.TextBoxFor(model => model.FirstSetList[i].Amount)
#Html.ValidationMessageFor(model => model.FirstSetList[i].Amount)
</td>
</tr>
}
<input type="submit" value="Confirm" class="btn btn-success" />
}
</table>
</div>
My Controller:
[HttpPost]
public JsonResult Divisibility(int valueToCheck)
{
var value = User.Identity.GetUserId().Where(x => x.Equals("qqqqq"));
//I know that this condition does not make sense, but this was only for test.
//Anyway like i said, chrome doesn't send anything to this method.
return Json(value == null);
}
The longer solution, and maybe better, would be to create your own validator in javascript using the same validators that MVC is using. But, to something someone else mentioned, server side validation. Use DataAnnotations with the Remote attribute and you can accomplish the same.
http://www.tugberkugurlu.com/archive/asp-net-mvc-remote-validation-for-multiple-fields-with-additionalfields-property
You will create a server method to do the validation but the front end will be calling it. The link I provided should give you all that you need.
I don't know why, but when i'll run application then this button is displaying above table. This button should be below this table. How can I fix this?
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.MyList.FirstOrDefault().Name)
</th>
<th>
#Html.DisplayNameFor(model => model.MyList.FirstOrDefault().Amount)
</th>
</tr>
#using (Html.BeginForm())
{
#Html.ValidationSummary("", new { #class = "text-danger" })
<br />
for (var i = 0; i < Model.MyList.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(model => model.MyList[i].Name)
#Html.HiddenFor(model => model.MyList[i].Name)
</td>
<td>
#Html.TextBoxFor(model => model.MyList[i].Amount)
#Html.HiddenFor(model => model.MyList[i].Amount)
</td>
</tr>
}
<input type="submit" value="Confirm" class="btn btn-success" />
}
</table>
Try this. You are mixing your table code with the rest of the Html
#using (Html.BeginForm())
{
#Html.ValidationSummary("", new { #class = "text-danger" })
<br />
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.MyList.FirstOrDefault().Name)
</th>
<th>
#Html.DisplayNameFor(model => model.MyList.FirstOrDefault().Amount)
</th>
</tr>
#for (var i = 0; i < Model.MyList.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(model => model.MyList[i].Name)
#Html.HiddenFor(model => model.MyList[i].Name)
</td>
<td>
#Html.TextBoxFor(model => model.MyList[i].Amount)
#Html.HiddenFor(model => model.MyList[i].Amount)
</td>
</tr>
}
</table>
<input type="submit" value="Confirm" class="btn btn-success" />
}
I have 3 views (1 Index, 2 Contacts(partialview), 3 Details(partialview))
I have a database with 2 tables tied by ContactId that i can use to get the Details from the database to show. I used ADO to make a model of the database. The 2 tables (classes) are named Contact and ContactTelefon.
Instead of button I tried using #html.ActionLink (as u can see in Contact View) to get the Id from the row, but that takes me to a new page, and it doesn't even show details.
My question is: How could i get the details to show in textboxes so i can edit the data.
All actions must be in same view as far as the user is concerned.
Controller:
ContactsDbEntities db = new ContactsDbEntities();
[HttpGet] //Index
public ActionResult Index()
{
return View();
}
//Contacts
public ViewResult Contacts()
{
var contactsList = db.Contacts.ToList();
return View(contactsList);
}
//Details
public ActionResult Details(int? id)
{
ContactTelefon contactTel = db.ContactTelefons.Find(id);
return View(contactTel);
}
Index view
#using Demo.Models
#model Contact
#section scripts
{
<link href="~/Content/jquery-ui.min.css" rel="stylesheet" />
<script src="~/Scripts/jquery-ui.min.js"></script>
<script src="~/Scripts/jquery-ui.js"></script>
<script>
$(function () {
$(document).on('click', '#Details', function () {
$.get('#Url.Action("Details","Home")', function (data) {
$('#divDetails').replaceWith(data);
});
});
</script>
}
<table id="mainTable" class="table table-bordered table-striped">
<tr>
<th>
#Html.DisplayNameFor(model => model.ContactId)
</th>
<th>
#Html.DisplayNameFor(model => model.Nume)
</th>
<th>
#Html.DisplayNameFor(model => model.Prenume)
</th>
<th>
#Html.DisplayNameFor(model => model.Adresa)
</th>
<th>
#Html.DisplayNameFor(model => model.Mentiuni)
</th>
</tr>
<tr>
<th>
</th>
#using (Html.BeginForm())
{
<th>
#Html.TextBoxFor(model => model.Nume, null, new { id = "txtSearchNume", #class = "form-control" })
</th>
<th>
#Html.TextBoxFor(model => model.Prenume, null, new { id = "txtSearchPrenume", #class = "form-control" })
</th>
<th>
#Html.TextBoxFor(model => model.Adresa, null, new { id = "txtSearchAdresa", #class = "form-control" })
</th>
<th>
#Html.TextBoxFor(model => model.Mentiuni, null, new { id = "txtSearchMentiuni", #class = "form-control" })
</th>
<th>
<input type="submit" value="Create" class="btn btn-success"
onclick=" location.href='#Url.Action("Index", "Home")' " />
</th>
<th>
<input type="submit" name="submitSearch" value="Search" class="btn btn-info"
onclick=" location.href='#Url.Action("Create", "Home")' " />
</th>
<tr>
#{Html.RenderAction("Contacts", "Home");}
</tr>
<tr><div id="divDetails"></div></tr>
}
</table>
Contacts View
#using Demo.Models
#model IEnumerable<Contact>
<table class="table table-bordered table-hover">
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ContactId)
</td>
<td>
#Html.DisplayFor(modelItem => item.Nume)
</td>
<td>
#Html.DisplayFor(modelItem => item.Prenume)
</td>
<td>
#Html.DisplayFor(modelItem => item.Adresa)
</td>
<td>
#Html.DisplayFor(modelItem => item.Mentiuni)
</td>
<td>
#Html.ActionLink("Delete", "Delete", new { id = item.ContactId },
new { #class = "btn btn-danger", onclick = "return confirm('Delete this record?');" })
</td>
<td>
<input id="Details" type="button" name="Details"
value="Details" class="btn btn-info" />
</td>
<td>
#Html.ActionLink("DetailsLink","Details",new{id = item.ContactId})
</td>
</tr>
}
</table>
Details View
#using Demo.Models
#model ContactTelefon
<div class="form-horizontal">
<div claass="form-group">
#* must get the id from Contacts *#
#Html.LabelFor(model => model.ContactId)
#Html.LabelFor(model => model.ContactTelefonId)
#Html.LabelFor(model => model.NumarTelefon)
#Html.LabelFor(model => model.TipNumarTelefon)
</div>
<br />
<div claass="form-group">
#Html.DisplayFor(model => model.ContactId)
#Html.DisplayFor(model => model.ContactTelefonId)
#Html.DisplayFor(model => model.NumarTelefon)
#Html.DisplayFor(model => model.TipNumarTelefon)
</div>
<div claass="form-group">
#Html.EditorFor(model => model.ContactId)
#Html.EditorFor(model => model.ContactTelefonId)
#Html.EditorFor(model => model.NumarTelefon)
#Html.EditorFor(model => model.TipNumarTelefon)
</div>
</div>
It seems as if you're starting MVC coming from ASP.NET WebForms. The thing about MVC is that it doesn't do any magic like WebForms so you have to have a good understanding of what happens behind the scenes to be able to make a smooth transition. Also, from the looks of it your database model uses Entity Framework.
First off the way you're handling the Details button is all wrong. What you should be doing is this:
HTML
<input type="button" name="Details" value="Details" class="btn btn-info js-details"
data-id="#item.ContactId" />
JavaScript
$(document).on('click', '.js-details', function (event) {
// get the element that triggered the event
var $element = $(event.currentTarget);
var id = $element.data('id');
// you might have to type in the literal URL if you have a custom route
// here
$.get('#Url.Action("Details","Home")'+ '?id=' + id, function (data) {
$('#divDetails').html(data);
});
});
Let me know if this works for you. There are other things that you can improve but this should be a pretty good start.
I am getting this error when trying to load a partial view, and I don't know what the issue is:
System.InvalidOperationException: The model item passed into the
dictionary is of type 'CDB.OrderM', but this dictionary requires a
model item of type
'System.Collections.Generic.IEnumerable`1[CDB.tblItem]'.
public ActionResult Index()
{
OrderM om = new OrderM();
List<tblItem> tList = db.Query<tblItem>("Select * from tblItem").ToList<tblItem>();
ViewBag.tList = tList;
return View(om);
}
public ActionResult Reqitem()
{
//tblItem ti= db.Query<tblItem>("select * from tblItem");
var ti = db.Query<tblItem>("select * from tblItem");
return PartialView("_rawmat",ti);
}
My Partial View codes are-
#model IEnumerable<CDB.tblItem>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.ItemId)
</th>
<th>
#Html.DisplayNameFor(model => model.ItemName)
</th>
<th>
#Html.DisplayNameFor(model => model.MeasuringUnit)
</th>
<th>
#Html.DisplayNameFor(model => model.Rate)
</th>
<th>
#Html.DisplayNameFor(model => model.Quantity)
</th>
<th>
#Html.DisplayNameFor(model => model.BagSz)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ItemId)
</td>
<td>
#Html.DisplayFor(modelItem => item.ItemName)
</td>
<td>
#Html.DisplayFor(modelItem => item.MeasuringUnit)
</td>
<td>
#Html.DisplayFor(modelItem => item.Rate)
</td>
<td>
#Html.DisplayFor(modelItem => item.Quantity)
</td>
<td>
#Html.DisplayFor(modelItem => item.BagSz)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
and Index view codes are...
#model CDB.OrderM
#{
ViewBag.Title = "Index";
var tList = ViewBag.tList;
}
<h2>Index</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>OrderM</legend>
<div class="editor-label">
#Html.LabelFor(model => model.OdrId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.OdrId)
#Html.ValidationMessageFor(model => model.OdrId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.OrderNo)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.OrderNo)
#Html.ValidationMessageFor(model => model.OrderNo)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.OdrDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.OdrDate)
#Html.ValidationMessageFor(model => model.OdrDate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.OdrQty)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.OdrQty)
#Html.ValidationMessageFor(model => model.OdrQty)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.OdrAmount)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.OdrAmount)
#Html.ValidationMessageFor(model => model.OdrAmount)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.DDate)
#Html.ValidationMessageFor(model => model.DDate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.CId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CId)
#Html.ValidationMessageFor(model => model.CId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Pod)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Pod)
#Html.ValidationMessageFor(model => model.Pod)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
#Html.Partial("_rawmat")
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
It looks like what you want to do is change #Html.Partial("_rawmat") to #Html.Action("Reqitem"). This is because your original statement says go straight to the view and since you haven't passed a model it will pass the same model as the view that it is included on.
So if you use #Html.Partial("_rawmat") on your index view it will pass the model that it has which is of type OrderM and not actually call the action you have written at all.
I dont know why you people are missing out the available syntax to call a partial view with a model
{#Html.RenderPartial("_PartialView",List<CDB.tblItem>) }
Where I assume the partial view uses the Model of type List<CDB.tblItem>.
If you want to populate the model with any values. just before the above syntax use
#{
//code to populate your model
}
If your partial view is expecting a List, then change the method like this...
public ActionResult Reqitem()
{
//tblItem ti= db.Query<tblItem>("select * from tblItem");
var ti = db.Query<tblItem>("select * from tblItem").ToList();//notice to List
return PartialView("_rawmat",ti);
}
I have added .ToList() to the end of the query.
I think the issue is in the second call of #Html.Partial("_rawmat") inside your Index.
It does not pass a model parameter, so it passed the default one, which is a CDB.OrderM.
Use this instead (it renders the action instead of the partial view):
#Html.Action("Reqitem")
I'm writing my first MVC3 application which is a simple order tracking application. I would like to edit the order and the details at the same time. When I edit the order the ActionResult for the Edit returns the order and the associated line (i'm using EF as well).
public ActionResult Edit(int id)
{
// Get the order with the order lines
var orderWithLines = from o in db.Orders.Include("OrderLines")
where o.ID == id
select o;
// Not sure if this is the best way to do this.
// Need to find a way to cast to "Order" type
List<Order> orderList = orderWithLines.ToList();
Order order = orderList[0];
// Use ViewData rather than passing in the object in the View() method.
ViewData.Model = order;
return View();
}
The order and the lines display with no issue but when I save the page I do not get any of the lines passed back to the controller. Only the order. Here is the View code.
#model OrderTracker.Models.Order
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
<fieldset>
<legend>Order</legend>
#Html.HiddenFor(model => model.ID)
#Html.HiddenFor(model => model.UserId)
<div>
#Html.LabelFor(model => model.OrderDate)
</div>
<div>
#Html.EditorFor(model => model.OrderDate)
</div>
<div>
#Html.LabelFor(model => model.Description)
</div>
<div>
#Html.EditorFor(model => model.Description)
</div>
<table>
<tr>
<th>
Description
</th>
<th>
Quantity
</th>
<th>
Weight
</th>
<th>
Price
</th>
<th></th>
</tr>
#foreach (var line in Model.OrderLines)
{
<tr>
<td>
#Html.EditorFor(modelItem => line.Description)
</td>
<td>
#Html.EditorFor(modelItem => line.Quantity)
</td>
<td>
#Html.EditorFor(modelItem => line.Weight)
</td>
<td>
#Html.EditorFor(modelItem => line.Price)
</td>
</tr>
}
</table>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
Can I please get some guidance on the best way to save the line data as well as the order data.
Thanks.
The issue that you are facing is related to the names generated by the ICollection<T> controls. Here is a detailed discussion by Phil Haack and a solution by him (in terms of an #Html extension method; download the sample project from the link given at the end of his blog post). This post targets MVC/MVC2; however it is still applicable with MVC3.
Alternatively if you don't want to follow the hack, you can opt for a EditorTemplate for your OrderLine entity model.
Here are the steps.
1) Create Editor template under (Views ->Shared -> EditorTemplates -> OrderLine.cshtml)
It is important to create a folder named EditorTemplates under Shared, and the template name should be same as the EntityModel for which you want to create the templete; hence the name OrderLine.cshtml)
2) Code for OrderLine.cshtml
#model OrderTracker.Models.OrderLine
#{
Layout = null;
}
<!DOCTYPE html>
#Html.HiddenFor(modelItem => Model.id)
<tr>
<td>
#Html.EditorFor(modelItem => Model.Description)
</td>
<td>
#Html.EditorFor(modelItem => Model.Quantity)
</td>
<td>
#Html.EditorFor(modelItem => Model.Weight)
</td>
<td>
#Html.EditorFor(modelItem => Model.Price)
</td>
</tr>
3) Edit your View with this code (note that I've used EditorFor for OrderLines collection)
#model OrderTracker.Models.Order
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
<fieldset>
<legend>Order</legend>
#Html.HiddenFor(model => model.ID)
#Html.HiddenFor(model => model.UserId)
<div>
#Html.LabelFor(model => model.OrderDate)
</div>
<div>
#Html.EditorFor(model => model.OrderDate)
</div>
<div>
#Html.LabelFor(model => model.Description)
</div>
<div>
#Html.EditorFor(model => model.Description)
</div>
<div>
<table>
<tr>
<th>
Description
</th>
<th>
Quantity
</th>
<th>
Weight
</th>
<th>
Price
</th>
</tr>
#Html.EditorFor(model => model.OrderLines)
</table>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
4) Now on post back you will see the values
Using MVC it should be rather straight forward as the framework is designed to to turn a form into a model.
[HttpGet]
public ActionResult Edit(int id)
{
// (you can probably rewrite this using a lambda
var orderWithLines = from o in db.Orders.Include("OrderLines")
select o;
// Use ViewData rather than passing in the object in the View() method.
ViewData.Model = orderWithLines.FirstOrDefault(x => x.ID = id);
return View();
}
[HttpPost]
public ActionResult Edit(OrderTracker.Models.Order model)
{
if (ModelState.IsValid)
{
// call the service layer / repository / db to persist the object graph
_service.Save(model); // this assumes your view models are the same as your domain
}
}
The issue is with your foreach if you look at the raw html that it produces it will not be generating unique ids for each of the order lines and thus will not be able to bind the model when the form is posted back.
Change the foreach to a for loop and then reference each orderline using the index. This will allow for unique ids to be generated in the form and allow you to bind the to the model when it is posted back.
e.g.
#for (var counter = 0; counter < Model.OrderLines.Count(); counter++)
{
<tr>
<td>
#Html.EditorFor(modelItem => Model.OrderLines[counter].Description)
</td>
<td>
#Html.EditorFor(modelItem => Model.OrderLines[counter].Quantity)
</td>
<td>
#Html.EditorFor(modelItem => Model.OrderLines[counter].Weight)
</td>
<td>
#Html.EditorFor(modelItem => Model.OrderLines[counter].Price)
</td>
</tr>
}
</table>