The code below works fine but, in the textbox the decimal value has this format "0,0000"
(, is the decimal separator). I'd like have only 2 decimal. How can I do this ?
Thanks,
//Database model used with NHibernate
public class Bank
{
public virtual int Id { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName{ get; set; }
public virtual decimal Amount { get; set; }
}
//MVC Model
public class MyModel
{
public Bank Bank { get; set; }
}
//View
#Html.TextBoxFor(m => m.Bank.Amount, new { id = "tbAmount"})
Update 1
In the debugger, I don't see any decimal, wehn I do step by step inside (o #HTML.Textbofor) the view, the value does not have any decimal but when the page is displayed there are 4 decimals
//Database model used with NHibernate
public class Bank
{
public virtual int Id { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName{ get; set; }
public virtual decimal Amount { get; set; }
}
//Class for view
public class ViewBank
{
[DisplayFormat(DataFormatString = "{0:n2}", ApplyFormatInEditMode = true)]
public decimal Amount { get; set; }
}
//MVC Model
public class MyModel
{
public Bank Bank { get; set; }
var ViewBank = new ViewBank() { Amount = Bank.Amount};
}
//View
#Html.TextBoxFor(m => m.Amount, new { id = "tbAmount"})
I would use editor templates and I would not use my NHibernate domain models in my views. I would define view models which are specifically tailored to the requirements of the given view (in this case limiting the amount to 2 decimals):
[DisplayFormat(DataFormatString = "{0:n2}", ApplyFormatInEditMode = true)]
public decimal Amount { get; set; }
and then:
#Html.EditorFor(m => m.Bank.Amount)
This works for me
#Html.TextBox("Amount", String.Format("{0:0.00}", Model.Bank.Amount), new { id = "tbAmount"})
EDIT:
This is for TextBoxFor (does not work on MVC3)
#{var formated = String.Format("{0:0.00}", Model.Bank.Amount);}
#Html.TextBoxFor(m => m.Bank.Amount, formated, new { id = "tbAmount"})
In MVC 4 you can now pass the format as the second parameter
//View
#Html.TextBoxFor(m => m.Bank.Amount, "{0:n2}", new { id = "tbAmount"})
If you don't have customized editor template for Decimal type then EditorFor decorated with DisplayFormatAttribute would probably work out of the box.
For a custom editor template I ended up using something like:
#model decimal?
#{
string displayValue;
if (Model == null)
{
displayValue = null;
}
else {
var formatString = (ViewData.ModelMetadata).DisplayFormatString;
displayValue = formatString == null ? Model.ToString() : string.Format(formatString, Model);
}
}
<div class="form-group">
#Html.LabelFor(c => c)
#Html.TextBoxFor(c => c, new { type = "text", Value = displayValue, #class = "form-control" })
#Html.ValidationMessageFor(c => c)
</div>
Which works when the property is decorated with DisplayFormatAttribute like so:
[DisplayFormat(DataFormatString = "{0:n1}", ApplyFormatInEditMode = true), Display(Name = "Commission")]
public decimal? CommissionPercentage { get; set; }
This works for me.
in MVC5, in View:
#Html.TextBoxFor(o => o.Amount, "{0:n0}", new { #class = "form-control" })
Output before StringFormatting --> 15000.00
Output after StringFormatting --> 15000
Related
I'm having a problem with my ASP.NET MVC web application where it takes ~30 seconds for my ViewModel to hit my controller when the form is posted. I'm guessing it has to do with the default Model Binder because of this.
[HttpPost]
public ActionResult Edit(ByActivityEditViewModel viewModel)
{
if (ModelState.IsValid) // Takes ~30 seconds before even hitting this
{
My View is a series of nested checkboxes of Group parents and User children. The same User may be listed under multiple Groups. I'm using an EditorFor to generate the checkboxes for the ViewModel.
View's Editor Template Call: #Html.EditorFor(model => model.Groups)
Editor Template:
#model MyProject.Models.Group
#Html.HiddenFor(model => model.Guid)
#Html.HiddenFor(model => model.Name)
#Html.CheckBoxFor(model => model.IsAllowed, new { #class = Model.Guid.ToString(), #style = "margin-right:5px; cursor:pointer;" }) #Html.LabelFor(model => model.IsAllowed, Model.Name, new { #class = "build-checkbox-label", #style = "font-weight:normal; margin-top:-2px;" })
#if (Model.Users.Any())
{
<ul style="list-style:none;">
#for (int i = 0; i < Model.Users.Count; i++)
{
<li>
#Html.HiddenFor(model => Model.Users[i].Guid)
#Html.HiddenFor(model => Model.Users[i].Name)
#Html.CheckBoxFor(model => Model.Users[i].IsAllowed, new { #class = Model.Users[i].Guid.ToString(), #style = "margin-right:5px; cursor:pointer;" }) #Html.LabelFor(model => Model.Users[i].IsAllowed, Model.Users[i].Name, new { #class = "build-checkbox-label", #style = "font-weight:normal; margin-top:-2px;" })
</li>
}
</ul>
}
ViewModel:
public class ByActivityEditViewModel
{
public int ActivityId { get; set; }
public string Path { get; set; }
public IList<Group> Groups { get; set; } = new List<Group>();
}
public class Group
{
public Guid? Guid { get; set; }
public string Name { get; set; }
public string DistinguishedName { get; set; }
public string SamAccountName { get; set; }
public string DisplayName { get; set; }
public bool IsAllowed { get; set; }
public List<User> Users { get; set; } = new List<User>();
}
public class User
{
public Guid? Guid { get; set; }
public string Name { get; set; }
public string DistinguishedName { get; set; }
public string SamAccountName { get; set; }
public string DisplayName { get; set; }
public bool IsAllowed { get; set; }
public bool IsUserChecked { get; set; }
}
ModelState:
The Model State contains the Guids, Names, and IsAllowed values. I believe processing this is the slow part.
There ends up being:
64 Groups
853 Users
The user can be part of more than one group.
I've tried:
Using string for Guid and Parsing it later.
Removing BeginCollectionItem package I was using.
Yelling at my monitor.
Any suggestions, information, or a workaround would be appreciated.
Jquery/js functions have done this for me previously a couple times, when handling large number of controls and i have banged my head trying to figure it out. Now I know where to look first.
So it is not clear from the post what is the fix unless you read the comments. So the answer is to add #{ Html.EnableClientValidation(false); } before #using (Html.BeginForm())
This turns off default client side validation and makes you form post faster to the server. Ofcourse if you need client side validation, then this is not the solution. In my case, my form had 200 rows with checkboxes and I didn't need the client side validation. So this solution worked great for me.
Model Class:
public class Course
{
[Key]
public int Id { get; set; }
[MinLength(5, ErrorMessage = "Code must be (5) characters long")]
[Index(IsUnique = true)]
[Column(TypeName = "VARCHAR")]
[Required]
[Display(Name = "Code")]
public string CourseCode { get; set; }
[Index(IsUnique = true)]
[Column(TypeName = "VARCHAR")]
[Required]
[Display(Name = "Name")]
[Remote("IsCourseNameExist", "Courses", HttpMethod = "POST", ErrorMessage = "Course is existed.")]
public string CourseName { get; set; }
//[System.ComponentModel.DataAnnotations.Compare("CourseName", ErrorMessage = "Already this Course is exist.")]
//[NotMapped]
//public string VeryfyName { get; set; }
[Range(0.5, 5, ErrorMessage = "Credit Must be between (0.5) to (5.0)")]
[Display(Name = "Credit")]
public decimal CourseCredit { get; set; }
public string Description { get; set; }
public int DepartmentId { get; set; }
public int SemesterId { get; set; }
[ForeignKey("DepartmentId")]
public virtual Department Department { get; set; }
[ForeignKey("SemesterId")]
public virtual Semester Semester { get; set; }
}
In Controller Class:
public JsonResult IsCourseNameExist(string CourseName)
{
//var course = .....
return Json(course == null);
}
In View:
<div class="form-group">
#Html.LabelFor(model => model.CourseName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CourseName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CourseName, "", new { #class = "text-danger" })
</div>
</div>
Description:
I am using Code First EF and very new in this area.
I have a Model class "Course" which generated a DB table named "Courses".
In view, user will add courses for a selected department and semester. But the Course Name property is unique.If user give a course name already exist in "Courses" table and submit button, then some error generates. That's why I want to make confirm that the user can not put any existing course name. So it needs checking before submission.
I have searched a lot, as I am newbie, everything is not clear to me. I found a way to use [Remote()] in model class and then use an action in controller to solve this. But cant apply it.
I expect some brief how to write the code that I mentioned in Controller class and what additional things need to add in view.
Thanks!
You can use a conditional statement combined with .Any() lambda expression.
public JsonResult IsCourseNameExist(string CourseName)
{
if(dbContext.Courses.Any(x => x.CourseName.Trim().ToUpper().Equals(CourseName.Trim().ToUpper())
{
return Json(false);
}
else
{
return Json(true);
}
}
Using .ToUpper() will help this be more efficient, because if your table you have a course name called Math 101.. and the user types in math 101 that might be submitted without error.
Let me know if this helps.
I wanna implement MVC paging so on the Index Action its working.
public ActionResult Index(int? page)
{
using (NorthwindEntities db = new NorthwindEntities())
{
CustomersViewModel model = new CustomersViewModel();
//model.Customers = db.Customers.OrderBy(m => m.CustomerID).OrderByDescending(m=>m.CustomerID).Take(10).ToList();
model.Customers = db.Customers.OrderBy(m => m.CustomerID).OrderByDescending(m=>m.CustomerID).Take(10).ToList().ToPagedList(page ?? 1,5);
model.SelectedCustomer = null;
var list = new List<int>();
for (int i = 1; i <= 20; i++)
{
list.Add(i);
}
SelectList selectedList = new SelectList(list);
ViewBag.DdList = selectedList;
//model.Countries = db.Countries.ToList();
model.CountryList = new SelectList(BLDDLCountry.GetCountry(), "CountryId", "CountryName");
model.DisplayMode = "WriteOnly";
return View(model);
}
}
Now on the View
#Html.PagedListPager(Model, page => Url.Action("Index", new {page, pagesize = 5 }))
Is accepted only if i decorate my View Model with IPagedList
#model PagedList.IPagedList<SingleCRUD.Models.CustomersViewModel>
Now as I am using
public IEnumerable<Customer> Customers { get; set; }
On My ViewModdel
The View is not accepting the Customers
#{
foreach (var item in Model.Customers)
{
if (Model.SelectedCustomer != null)
{
if (item.CustomerID ==
Model.SelectedCustomer.CustomerID)
{
#:<tr class="SelectedCustomer">
}
else
{
#:<tr>
}
}
else
{
#:<tr>
}
<td>#item.CustomerID</td>
<td>#item.CompanyName</td>
#*<td><input type="submit"
formaction="/home/select/#item.CustomerID"
value="Select" /></td>*#
<td><input type="submit"
formaction="/home/Edit/#item.CustomerID"
value="Edit" /></td>
<td></td>
#:</tr>
}
}
And Go to definition has stopped on Customers after changing the name space.
My View Model
public class CustomersViewModel
{
public int CustomerID { get; set; }
public string CompanyName { get; set; }
public string ContactName { get; set; }
public string ContactTitle { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Region { get; set; }
public Nullable<int> PostalCode { get; set; }
public string Country { get; set; }
public Nullable<int> Phone { get; set; }
public Nullable<int> Fax { get; set; }
public IEnumerable<Customer> Customers { get; set; }
public Customer SelectedCustomer { get; set; }
public string DisplayMode { get; set; }
public List<Country> Countries { get; set; }
public SelectList CountryList { get; set; }
}
So I am facing issue at the view level how do I correctly fix it.
Tried these changes
Model
public PagedList<Customer> Customers { get; set; }
View
#model SingleCRUD.Models.CustomersViewModel
#using PagedList;
#using PagedList.Mvc;
#Html.PagedListPager(Model.Customers, page => Url.Action("Index", new { page, pagesize = 5 }))
Action
model.Customers = (PagedList<Customer>)db.Customers.OrderBy(m => m.CustomerID).ToPagedList(page ?? 1, 5);
Had to explicitly convert it to Paged List as there was a conversion error not sure whether its correct.
Run Time error on View.
'System.Web.Mvc.HtmlHelper' does not contain a definition for 'PagedListPager' and the best extension method overload 'PagedList.Mvc.HtmlHelper.PagedListPager(System.Web.Mvc.HtmlHelper, PagedList.IPagedList, System.Func)' has some invalid arguments
Error
Error 1 Cannot implicitly convert type 'PagedList.IPagedList' to 'PagedList.PagedList'. An explicit conversion exists (are you missing a cast?)
Using
#Html.PagedListPager(Model.Customers, page => Url.Action("Index", new { page, pagesize = 5 }))
on View tried writing this in the form tag as well as out side the form tag.
Its a bit unclear what you claiming. #model PagedList.IPagedList<CustomersViewModel> will not work since your model is CustomersViewModel but it will work if your use #model CustomersViewModel.
If you wanting to display a paged list of Customer, then your model property needs to be
public IPagedList<Customer> Customers { get; set; }
and in the view use
#Html.PagedListPager(Model.Customers, page => Url.Action("Index", new {page, pagesize = 5 }))
I´m having a problem creating a DropDownListFor using a relation between to tables that are related on an entity code first:
public class Motivo_Agenda
{
[Key]
[Required]
public string DESC_MOTIVO { get; set; }
}
public class Agenda // Agenda da produção
{
[Key]
public int ID_AGD { get; set; }
[Required]
public DateTime DATA_AGD { get; set; }
[Display(Name = "De")]
public TimeSpan DE { get; set; }
[Required]
[Display(Name = "Até")]
public TimeSpan ATE { get; set; }
[Required]
public virtual Motivo_Agenda MOTIVO_AGENDA { get; set; }
}
I´m tryng to create a Drop Down List to add a new item to the Agenda Table this is my controller:
bAxaltaModel dbAxalta = new dbAxaltaModel();
// GET: Agenda
public ActionResult Edit()
{
ViewBag.MOTIVO_AGENDA = new SelectList(dbAxalta.Motivos_Agenda, "DESC_MOTIVO", "DESC_MOTIVO");
return View();
}
[HttpPost]
public ActionResult Edit([Bind(Include = "DE,ATE,DATA_AGD,FLAG_SAB_DOM,MOTIVO_AGENDA")]Agenda Agendas)
{
var errors = ModelState.Values.SelectMany(v => v.Errors).ToList();
if (ModelState.IsValid != false)
{
dbAxalta.Agendas.Add(Agendas);
dbAxalta.SaveChanges();
var query = dbAxalta.Agendas.Where(m => m.DATA_AGD == Agendas.DATA_AGD);
TempData["Agendas"] = query.ToList();
return View();
}
ViewBag.MOTIVO_AGENDA = new SelectList(dbAxalta.Motivos_Agenda, "DESC_MOTIVO", "DESC_MOTIVO", Agendas.MOTIVO_AGENDA);
return View();
}
And my DropDown is this:
#Html.DropDownListFor(m => m.MOTIVO_AGENDA, ViewBag.MOTIVO_AGENDA as SelectList, htmlAttributes: new { #class = "form-control" })
But I´m getting the following error:
The parameter conversion from type 'System.String' to type 'Axalta_Project.Models.Motivo_Agenda' failed because no type converter can convert between these types.
Any ideas how can I bind these?
When using DropDownListFor, the first parameter is the selected value so you will need to add this to your model.
Ideally, use a Model class rather than ViewBag in a similar format to the following:
public class MyModel {
public int SelectedAgendaId {get; set;}
public SelectList Agendas {get;set;}
}
Then use something like this:
#Html.DropDownListFor(m => m.SelectedAgendaId, Model.Agendas, htmlAttributes: new { #class = "form-control" })
I am trying to save data using SelectListItem. I have managed to display the data but, I can't think of a way to save a selected item into the database.
My controller methods are:
public ActionResult Create()
{
ViewBag.ProposerID = new SelectList(db.Proposers, "ID", "ProposerName");
List<SelectListItem> projectType = new List<SelectListItem>();
projectType.Add(new SelectListItem { Text = "Development", Value = "1" });
projectType.Add(new SelectListItem { Text = "Research", Value = "2" , Selected = true});
projectType.Add(new SelectListItem { Text = "Hybrid", Value = "3" });
projectType.Add(new SelectListItem { Text = "Other", Value = "4" });
ViewBag.ProjectType = projectType;
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(
[Bind(Include = "ID,ProjectTitle,Description,ProposedDate,ProjectType,ProjectStatus,ProjectDifficulty,ProposerID")] Project project)
{
try {
if (ModelState.IsValid && ModelState != ModelState)
{
db.Projects.Add(project);
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (Exception)
{
ViewBag.ErrorMessage = "Something went wrong!! Please try again.";
// Error message
}
ViewBag.ProposerID = new SelectList(db.Proposers, "ID", "ProposerName", project.ProposerID);
return View(project);
}
and my View:
<div class="form-group">
#Html.LabelFor(model => model.ProjectType, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("ProjectType", "")
#Html.ValidationMessageFor(model => model.ProjectType, "", new { #class = "text-danger" })
</div>
</div>
I have managed to display the data but, I am confused on how to get selected item and save it.
My Model is:
public class Project
{
public int ID { get; set; }
[Required]
[DisplayName("Project Title")]
public string ProjectTitle { get; set; }
[Required]
[DataType(DataType.MultilineText)]
[DisplayName("Project Description")]
public string Description { get; set; }
[Required]
[DataType(DataType.Date)]
[DisplayName("Proposed Date")]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime ProposedDate { get; set; }
// Development or Research etc.
[Required]
[DisplayName("Project Type")]
public string ProjectType { get; set; }
// Project Is Taken or Not
[DisplayName("Project Status")]
public ProjectStatus ProjectStatus { get; set; }
[DisplayName("Project Difficulty")]
public ProjectDifficulty ProjectDifficulty { get; set; }
[ForeignKey("Proposer")]
public int ProposerID { get; set; }
public virtual Proposer Proposer { get; set; }
}
First of all change you ViewBag key so it is different than the model property name:
ViewBag.ProjectTypeOptions = projectType;
and in your view use DropDownListFor helper this way:
#Html.DropDownListFor(x=>x.ProjectType, new SelectList(ViewBag.ProjectTypeOptions,"Value","Text"))
now you will get selecred item value posted in Model in ProjectType property.
and your model should have property of type string not IEnumerable<SelectListItem> like this:
public class Project
{
public string ProjectType { get;set;}
............
............
}