I'm using ASP.NET c# mvc with entity framework to build a web site. So I want to create user profile for the registered user which is editable. Within that i have coded for a image upload part and it was not successfully worked out for me.
This is my View file (Manage.cshtml)
#model TheFoody.Models.ManageViewModel
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script>
function editFunc() {
document.getElementById("Photo").disabled = false;
document.getElementById("FirstName").disabled = false;
document.getElementById("LastName").disabled = false;
document.getElementById("Email").disabled = false;
document.getElementById("UserType").disabled = false;
document.getElementById("Address").disabled = false;
document.getElementById("City").disabled = false;
document.getElementById("District").disabled = false;
document.getElementById("Phone").disabled = false;
//document.getElementById("Photo").disabled = false;
document.getElementById("PostCode").disabled = false;
document.getElementById("Status").disabled = false;
}
function reload() {
window.location.href = "http://localhost:1672/Manage";
}
</script>
<div class="breadcrumb-wrapper">
<div class="container">
<ol class="breadcrumb-list booking-step">
<li>Home</li>
<li><span>User Profile</span></li>
</ol>
</div>
</div>
<div class="admin-container-wrapper">
<div class="container">
<div class="GridLex-gap-15-wrappper">
<div class="GridLex-grid-noGutter-equalHeight">
<div class="GridLex-col-3_sm-4_xs-12">
<div class="admin-sidebar">
<div class="admin-user-item">
<div class="image">
<img src="http://localhost:33409/images/man/01.jpg" alt="image" class="img-circle" />
</div>
<h4>John Doe</h4>
<p class="user-role">Foodies</p>
</div>
<div class="admin-user-action text-center">
Edit
Deactivate
</div>
<ul class="admin-user-menu clearfix">
<li>
<i class="fa fa-tachometer"></i> Dashboard
</li>
<li class="active">
<i class="fa fa-user"></i> Profile
</li>
<li>
<i class="fa fa-key"></i> Change Password
</li>
<li>
<i class="fa fa-bookmark"></i> Favourite Restaurant
</li>
<li>
<i class="fa fa-sign-out"></i> Logout
</li>
</ul>
</div>
</div>
<div class="GridLex-col-9_sm-8_xs-12">
<div class="admin-content-wrapper">
<div class="admin-section-title">
<h2>Profile</h2>
<p>Enquire explain another he in brandon enjoyed be service.</p>
</div>
<!--<form class="post-form-wrapper" action="http://localhost:33409/UpdateProfile/Edit" id="updateForm" method="POST">-->
#using (Html.BeginForm("Manage", "Manage", new { #id = "updateForm", #class = "post-form-wrapper" }, FormMethod.Post))
{
#Html.AntiForgeryToken();
<div class="row gap-20">
<div class="col-sm-6 col-md-4">
#ViewBag.Error
<div class="form-group bootstrap-fileinput-style-01">
<label>Photo</label>
<input type="file" name="Photo" id="Photo" disabled>
#*#Html.HiddenFor(model => model.Photo, new { #class = "form-control", disabled = "disabled" })*#
#*<input type="hidden" value="default" id="photo" name="photo" />*#
<span class="font12 font-italic">** photo must not bigger than 250kb</span>
</div>
</div>
<div class="clear"></div>
<div class="col-sm-6 col-md-4">
<div class="form-group">
<label>First Name</label>
#Html.TextBoxFor(model => model.FirstName, new { #class = "form-control", disabled = "disabled" })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-sm-6 col-md-4">
<div class="form-group">
<label>Last Name</label>
#Html.TextBoxFor(model => model.LastName, new { #class = "form-control", disabled = "disabled" })
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-sm-6 col-md-4">
<div class="form-group">
<label>Email</label>
#*<input type="email" class="form-control" value=Session["UserEmail"].tostring() id="email" name="email" disabled>*#
#Html.TextBoxFor(model => model.Email, new { #class = "form-control", disabled = "disabled"})
#Html.ValidationMessageFor(model => model.Email, "", new { #class = "text-danger" })
</div>
</div>
<div class="clear"></div>
<div class="col-sm-6 col-md-4">
<div class="form-group">
<label>Address</label>
#*<input type="text" class="form-control" value="254" id="address" name="address" disabled>*#
#Html.TextBoxFor(model => model.Address, new { #class = "form-control", disabled = "disabled" })
#Html.ValidationMessageFor(model => model.Address, "", new { #class = "text-danger" })
</div>
</div>
<div class="clear"></div>
<div class="col-sm-6 col-md-4">
<div class="form-group">
<label>District</label>
#*<input type="text" class="form-control" value="254" id="district" name="district" disabled>*#
#Html.TextBoxFor(model => model.District, new { #class = "form-control", disabled = "disabled" })
#Html.ValidationMessageFor(model => model.District, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-sm-6 col-md-4">
<div class="form-group">
<label>City/town</label>
#*<input type="text" class="form-control" value="Somewhere " id="city" name="city" disabled>*#
#Html.TextBoxFor(model => model.City, new { #class = "form-control", disabled = "disabled" })
#Html.ValidationMessageFor(model => model.City, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-sm-6 col-md-4">
<div class="form-group">
<label>PostCode</label>
#*<input type="text" class="form-control" value="Somewhere " id="postcode" name="postcode" disabled>*#
#Html.TextBoxFor(model => model.PostCode, new { #class = "form-control", disabled = "disabled" })
#Html.ValidationMessageFor(model => model.PostCode, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-sm-6 col-md-4">
<div class="form-group">
<label>UserType</label>
</div>
<div class="col-sm-6 col-md-4">
#{
List<SelectListItem> listItemsUserType = new List<SelectListItem>();
listItemsUserType.Add(new SelectListItem
{
Text = "Admin",
Value = "Admin"
});
listItemsUserType.Add(new SelectListItem
{
Text = "Customer",
Value = "Customer",
Selected = true
});
listItemsUserType.Add(new SelectListItem
{
Text = "Business",
Value = "Business"
});
}
#Html.DropDownListFor(model => model.UserType, listItemsUserType, "-- Select Status --", new { #class = "form-control",disabled = "disabled" })
</div>
</div>
<div class="col-sm-6 col-md-4">
<div class="form-group">
<label>Status</label>
</div>
<div class="col-sm-6 col-md-4">
#{
List<SelectListItem> listItemsStatus = new List<SelectListItem>();
listItemsStatus.Add(new SelectListItem
{
Text = "Availble",
Value = "Available",
Selected = true
});
listItemsStatus.Add(new SelectListItem
{
Text = "Not Available",
Value = "Not Available"
});
}
#Html.DropDownListFor(model => model.Status, listItemsStatus, "-- Select Status --", new { #class = "form-control",disabled = "disabled" })
</div>
</div>
<div class="clear"></div>
<div class="col-sm-6 col-md-4">
<div class="form-group">
<label>Phone Number</label>
#*<input type="text" class="form-control" value="+66-85-221-5489" id="phone" name="phone" disabled>*#
#Html.TextBoxFor(model => model.Phone, new { #class = "form-control", disabled = "disabled" })
#Html.ValidationMessageFor(model => model.Phone, "", new { #class = "text-danger" })
</div>
</div>
<div class="clear"></div>
<div class="col-sm-12 mt-10">
#*<input type="submit" onclick="document.getElementById('updateform').submit()" class="btn btn-primary" value="Save" />*#
<input type="submit" class="btn btn-primary" value="Save" />
Cancel
</div>
</div>
}
<!--</form>-->
</div>
</div>
</div>
</div>
</div>
</div>
And it will give a UI like below.
And my Model file is like below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace TheFoody.Models
{
public class ManageViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Photo { get; set; }
public string Address { get; set; }
public string City { get; set; }
public int PostCode { get; set; }
public string District { get; set; }
public string UserType { get; set; }
public string Status { get; set; }
}
}
And my Controller looks like this (ManageController.cs)
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TheFoody.DataAccess;
using TheFoody.Models;
namespace TheFoody.Controllers
{
public class ManageController : Controller
{
//ManageContext db = new ManageContext();
//
//GET: /Manage/
public ActionResult Manage()
{
//LoadData();
var manageviewmodel = new ManageViewModel() { Email = Session["UserEmail"].ToString() };
return View(manageviewmodel);
}
private bool isValidContentType(string contentType)
{
return contentType.Equals("Images/png") || contentType.Equals("Images/gif") || contentType.Equals("Images/jpg") || contentType.Equals("Images/jpeg");
}
private bool isValidContentLength(int contentLength)
{
return (contentLength / 1024) / 1024 < 1; //1MB
}
[HttpPost]
public ActionResult Manage(ManageViewModel manageviewmodel, HttpPostedFileBase Photo)
{
TheFoodyContext db = new TheFoodyContext();
User user_to_update = db.Users.SingleOrDefault(s => s.email == manageviewmodel.Email);
if (ModelState.IsValid)
{
try
{
if (!isValidContentType(Photo.ContentType))
{
ViewBag.Error = "Only JPG , JPEG , GIF & PNG are allowed!";
return View("Manage");
}
else if (!isValidContentLength(Photo.ContentLength))
{
ViewBag.Error = "Your File is too Large!";
return View("Manage");
}
else
{
if (user_to_update != null && (Photo != null && Photo.ContentLength > 0))
{
var fileName = Path.GetFileName(Photo.FileName);
var path = Path.Combine(Server.MapPath("~/Content/Images"), fileName);
Photo.SaveAs(path);
user_to_update.email = manageviewmodel.Email;
user_to_update.fname = manageviewmodel.FirstName;
user_to_update.lname = manageviewmodel.LastName;
user_to_update.phone = manageviewmodel.Phone;
//user_to_update.photo = manageviewmodel.Photo;
user_to_update.address = manageviewmodel.Address;
user_to_update.city = manageviewmodel.City;
user_to_update.postcode = manageviewmodel.PostCode;
user_to_update.district = manageviewmodel.District;
user_to_update.user_type = manageviewmodel.UserType;
user_to_update.status = manageviewmodel.Status;
db.SaveChanges();
return RedirectToAction("Manage");
}
}
}
catch (Exception ex)
{
return View("Error");
}
return View(manageviewmodel);
}
return View(manageviewmodel);
}
}
}
And the design of My database is;
And my DbContext file looks as below;
namespace TheFoody.DataAccess
{
using System;
using System.Collections.Generic;
public partial class User
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public User()
{
this.Restaurants = new HashSet<Restaurant>();
}
public string email { get; set; }
public string password { get; set; }
public string fname { get; set; }
public string lname { get; set; }
public string phone { get; set; }
public string photo { get; set; }
public string address { get; set; }
public string city { get; set; }
public Nullable<decimal> postcode { get; set; }
public string district { get; set; }
public string user_type { get; set; }
public string status { get; set; }
public System.DateTime created_date { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Restaurant> Restaurants { get; set; }
}
}
But when i'm executing all these things My ~/Content/Images file does not have the image file that i have uploaded. And it will give me the error to the view as follows.
Actually I wanted to save the path to the relevant image file in the database and image in the ~/Content/Images folder which in following hierarchy.
I'm very new to this environment specially Entity Framework. So i don't know how to correct my code to get what i'm expected.
First you have to do is copy and past that image to your image folder
System.IO.File.Copy("source", "destination");
Then save that path to your data base.
Related
I'm trying to save data from the view to the database from one main view and 1 partial view. Here AppRequest is the main class and the others are Purchase, PurchasingEmpl, PurchasingItems.
But when I debug the code, to the controller AppRequest main view data will pass but other class data not showing. Also not passing to the other tables also. Can you help me with this?
These are my model classes:
public class AppRequest
{
[Key]
public int Id { get; set; }
[Required]
[Display(Name = "Request Type")]
public int ReqType { get; set; }
[Required]
[Display(Name = "Requesting By")]
public int Req_By { get; set; }
[Required]
[Display(Name = "Requesting Date")]
public DateTime Req_Date { get; set; } = DateTime.Now;
[Required]
[Display(Name = "Request Location")]
public int Req_Location { get; set; }
[Required]
[Display(Name = "Request Heading")]
public string Req_Heading { get; set; }
[Display(Name = "Cover Note")]
public string Req_CoverNote { get; set; }
[Required]
[Display(Name = "Company Name")]
public int Company_Id { get; set; }
public bool Status { get; set; }
public int Create_By { get; set; }
public DateTime Created_Date { get; set; }
public int Modified_By { get; set; }
public DateTime Modified_Date { get; set; } = DateTime.Now;
public int Approval_Status { get; set; }
public virtual IList<Purchase> Purchase { get; set; }
[NotMapped]
public Purchase PurchaseItem { get; set; }
}
#region Purchase
public class Purchase
{
[Key]
public int Id { get; set; }
[Required]
[ForeignKey("AppRequest")]
public int Req_Id { get; set; }
public virtual AppRequest AppRequest { get; set; }
public virtual IList<PurchasingEmpl> PurchasingEmpl { get; set; }
public virtual IList<PurchasingItems> PurchasingItems { get; set; }
}
public class PurchasingEmpl
{
[Key]
public int Id { get; set; }
[Required]
[ForeignKey("Purchase")]
public int Purchase_Id { get; set; }
public virtual Purchase Purchase { get; set; }
public int Emp_Id { get; set; }
public bool Status { get; set; }
}
public class PurchasingItems
{
[Key]
public int Id { get; set; }
[Required]
[ForeignKey("Purchase")]
public int Purchase_Id { get; set; }
public virtual Purchase Purchase { get; set; }
public int Supp_Id { get; set; }
public int Itm_Description_Id { get; set; }
public decimal Unit_Amount { get; set; }
public byte[] Attachment { get; set; }
public decimal Qty { get; set; }
public string Recomandation { get; set; }
public bool Status { get; set; }
public bool Settled { get; set; } = false;
public string PoNo { get; set; }
}
This is the controller
public ActionResult Create(AppRequest appRequest)
{
if (ModelState.IsValid)
{
appRequest.Create_By = int.Parse(((System.Security.Claims.ClaimsIdentity)User.Identity).FindFirst("UserId").Value);
appRequest.Created_Date = DateTime.Now;
appRequest.Modified_By= int.Parse(((System.Security.Claims.ClaimsIdentity)User.Identity).FindFirst("UserId").Value);
appRequest.Modified_Date = DateTime.Now;
appRequest.Status = true;
db.AppRequest.Add(appRequest);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(appRequest);
}
HTML View
````
#model Asp_PASMVC.Models.AppRequest
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
List<SelectListItem> ReqTypes = (List<SelectListItem>)TempData.Peek("RequestTyleList");
List<SelectListItem> Employees = (List<SelectListItem>)TempData.Peek("EmployeeList");
List<SelectListItem> Location = (List<SelectListItem>)TempData.Peek("LocationList");
List<SelectListItem> Companies = (List<SelectListItem>)TempData.Peek("ComapnyList");
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<!-- Default box -->
<div class="card">
<div class="card-header" >
<h3 class="card-title">Request Header Details</h3>
<div class="card-tools">
<button type="button" class="btn btn-tool" data-card-widget="collapse" title="Collapse">
<i class="fas fa-minus"></i>
</button>
<button type="button" class="btn btn-tool" data-card-widget="remove" title="Remove">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<div class="card-body">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="row">
<div class="col-md-6 col-sm-6">
<div class="form-group row">
#Html.LabelFor(model => model.ReqType, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-sm-8">
#Html.DropDownListFor(model => model.ReqType, ReqTypes, new { #class = "js-dropdown" })
#Html.ValidationMessageFor(model => model.ReqType, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="col-md-6 col-sm-6">
<div class="form-group row">
#Html.LabelFor(model => model.Company_Id, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-sm-8">
#Html.DropDownListFor(model => model.Company_Id, Companies, new { #class = "js-dropdown" })
#Html.ValidationMessageFor(model => model.Company_Id, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="col-md-6 col-sm-6">
<div class="form-group row">
#Html.LabelFor(model => model.Req_By, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-sm-8">
#Html.DropDownListFor(model => model.Req_By, Employees, new { #class = "js-dropdown" })
#Html.ValidationMessageFor(model => model.Req_By, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="col-md-6 col-sm-6">
<div class="form-group row">
#Html.LabelFor(model => model.Req_Location, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-sm-8">
#Html.DropDownListFor(model => model.Req_Location, Location, new { #class = "js-dropdown" })
#Html.ValidationMessageFor(model => model.Req_Location, "", new { #class = "text-danger" })
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="form-group row">
#Html.LabelFor(model => model.Req_Heading, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-6">
#Html.EditorFor(model => model.Req_Heading, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Req_Heading, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="col-md-6 col-sm-6">
<div class="form-group row">
#Html.LabelFor(model => model.Req_Date, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-sm-8">
#Html.EditorFor(model => model.Req_Date, new { htmlAttributes = new { #class = "js-datepicker" } })
#Html.ValidationMessageFor(model => model.Req_Date, "", new { #class = "text-danger" })
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="form-group row">
#Html.LabelFor(model => model.Req_CoverNote, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-6">
#Html.EditorFor(model => model.Req_CoverNote, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Req_CoverNote, "", new { #class = "text-danger" })
</div>
</div>
</div>
</div>
</div>
<!-- /.card-body -->
<!-- /.card-footer-->
</div>
<!-- /.card -->
</div>
</div>
</div>
</section>
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<!-- Default box -->
<div class="card">
<div class="card-header">
<h3 class="card-title">Request Main Details</h3>
<div class="card-tools">
<button type="button" class="btn btn-tool" data-card-widget="collapse" title="Collapse">
<i class="fas fa-minus"></i>
</button>
<button type="button" class="btn btn-tool" data-card-widget="remove" title="Remove">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<div class="card-body">
#Html.Partial("_Purchase", Model.PurchaseItem);
<!-- /.card-body -->
<div class="card-footer">
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
<!-- /.card-footer-->
</div>
<!-- /.card -->
</div>
</div>
</div>
</section>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
````
I have a page written using some fake data in my controller, to render some mock data in my view. Here is the code I have:
Model
Data View Model
[Required]
[Display(Name = "Is this a remix?")]
public bool IsRemix { get; set; }
[Required]
[Display(Name = "Does this song contain sample(s)?")]
public bool ContainsSample { get; set; }
I had this in my ViewModel
public bool IsRemix { get; set; }
public bool ContainsSample { get; set; }
Controller
model.Songs = songs;
model.SongTitle = "Darkside of the Moon";
model.AlternativeSongTitle = "Wish You Were Here";
model.DurationMinutes = 3;
model.DurationSeconds = 57;
model.IsRemix = true;
model.ContainsSample = false;
View
<div class="form-group">
<label class="control-label col-md-4 pull-left" for="SongTitle">Is a Remix</label>
<div class="col-md-8">
<div class="admin-form theme-primary">
<div class="radio-custom radio-primary mt10 mr10 pull-left">
#Html.RadioButtonFor(m => m.IsRemix, true, new { #class = "control-label col-md-4" })
<label for="IsRemixYes">Yes</label>
</div>
<div class="radio-custom radio-primary mt10 pull-left">
#Html.RadioButtonFor(m => m.IsRemix, true, new { #class = "control-label col-md-4" })
<label for="IsRemixNo">No</label>
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-4 pull-left" for="SongTitle">Contains Sample</label>
<div class="col-md-8">
<div class="admin-form theme-primary">
<div class="radio-custom radio-primary mt10 mr10 pull-left">
#Html.RadioButtonFor(m => m.ContainsSample, true, new { #class = "control-label col-md-4" })
<label for="ContainsSampleYes">Yes</label>
</div>
<div class="radio-custom radio-primary mt10 pull-left">
#Html.RadioButtonFor(m => m.ContainsSample, true, new { #class = "control-label col-md-4" })
<label for="ContainsSampleNo">No</label>
</div>
</div>
</div>
</div>
I am unsure how to get the radio buttons to be pre-selected.
This question already has answers here:
Post an HTML Table to ADO.NET DataTable
(2 answers)
Closed 4 years ago.
I have this ViewModel:
public class DepositViewModel
{
public DepositViewModel()
{
DepositDate = DateTime.Now;
CollectedReceipts = new List<DepositQuantityAmountViewModel>();
CancelledReceipts = new List<DepositQuantityAmountViewModel>();
}
[Display(Name = "Deposit #")]
public long DepositId { get; set; }
[Display(Name = "Deposit Type")]
public string DepositType { get; set; }
[Display(Name = "Cashier #")]
public int CashierId { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Deposit Date")]
[DisplayFormat(DataFormatString = "{0:dd-MMM-yyyy}", ApplyFormatInEditMode = true)]
public DateTime DepositDate { get; set; }
[Display(Name = "Collected Receipts")]
public IList<DepositQuantityAmountViewModel> CollectedReceipts { get; set; }
[Display(Name= "Cancelled Receipts")]
public IList<DepositQuantityAmountViewModel> CancelledReceipts { get; set; }
[Display(Name = "Finance Reference")]
[MaxLength(2000)]
public string FinanceReference { get; set; }
[Display(Name = "Received Amount")]
[DisplayFormat(DataFormatString = "{0:N2}", ApplyFormatInEditMode = true)]
public decimal ReceivedAmount { get; set; }
[Display(Name = "Payment Modes")]
public IList<BDOs.PayMode> PaymentModes { get; set; }
}
public class DepositQuantityAmountViewModel
{
[Display(Name = "Description")]
public string Description { get; set; }
[Display(Name = "Category")]
public string Category { get; set; }
[Display(Name = "Count")]
public int Count { get; set; }
[Display(Name = "Total")]
[DisplayFormat(DataFormatString = "{0:N2}", ApplyFormatInEditMode = true)]
public decimal Amount { get; set; }
}
In my view, I have this setup:
<div class="row">
<div class="col-sm-2">
<div class="form-group">
<fieldset>
<legend>#Html.DisplayNameFor(m => m.PaymentModes)</legend>
<div class="col-sm-12">
<div class="row">
#foreach (var modelPaymentMode in Model.PaymentModes)
{
#Html.DisplayFor(m => modelPaymentMode, "_DepositPartPaymentModes")
}
</div>
</div>
</fieldset>
</div>
</div>
<div class="col-sm-5">
<div class="form-group">
<fieldset>
<legend>#Html.DisplayNameFor(m => m.CollectedReceipts)</legend>
#Html.DisplayFor(m => m.CollectedReceipts, "_DepositPartDetail")
</fieldset>
</div>
</div>
<div class="col-sm-5">
<div class="form-group">
<fieldset>
<legend>#Html.DisplayNameFor(m => m.CancelledReceipts)</legend>
#Html.DisplayFor(m => m.CancelledReceipts, "_DepositPartDetail")
</fieldset>
</div>
</div>
</div>
And here are the display templates:
_DepositPartPaymentModes.cshtml
#model DA.Services.IBS.Business.BDO.PayMode
<div class="form-group">
#Html.TextBoxFor(m => m.Name, new { #class = "form-control", #readonly = "readonly" })
</div>
_DepositPartDetail.cshtml
#model IEnumerable<DA.Services.IBS.Web.FinancePortalFull.Models.DepositQuantityAmountViewModel>
#foreach (var countAmountPair in Model)
{
if (countAmountPair.Category == "TotalCollected" || countAmountPair.Category == "TotalCancelled")
{
<div class="col-sm-12">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
#Html.TextBoxFor(m => countAmountPair.Description, new { #class = "form-control", #readonly = "readonly" })
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
#Html.TextBoxFor(m => countAmountPair.Amount, "{0:N2}", new { #class = "form-control", type = "numeric", dir = "rtl", #readonly = "readonly" })
</div>
</div>
</div>
</div>
}
else
{
<div class="col-sm-12">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
#Html.TextBoxFor(m => countAmountPair.Count, "{0:N0}", new { #class = "form-control", type = "numeric", dir = "rtl", #readonly = "readonly" })
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
#Html.TextBoxFor(m => countAmountPair.Amount, "{0:N2}", new { #class = "form-control", type = "numeric", dir = "rtl", #readonly = "readonly" })
</div>
</div>
</div>
</div>
}
}
I have tried to bind each template separately looking at different guides. I cannot get the collections to be returned to postback as they are null. They display properly all three collections are null on submission.
What am I doing wrong?
Solution
Do not use ForEach Loops in views to iterate collections. Use For Loops.
The issue is in using foreach loops. When this is rendered in HTML, the input elements are not given names that will mean anything to the model binder when you post. You need to change these to for loops and the inputs will be rendered correctly.
You may also need to change your model so that the list is not null when the binder is trying to add to it.
Eg:
#for (int i = 0; i < Model.PaymentModes; i++)
{
#Html.DisplayFor(m => Model.PaymentModes[i], "_DepositPartPaymentModes")
}
Use for loop instead of foreach.
Element should be like this.
<input type="text" name="List[0].PropertyName" value="XYZ" />
change #model IEnumerable<DA.Services.IBS.Web.FinancePortalFull.Models.DepositQuantityAmountViewModel> to #model List<DA.Services.IBS.Web.FinancePortalFull.Models.DepositQuantityAmountViewModel>
_DepositPartDetail.cshtml
for (int i=0;i<Model.Count(); i++)
{
{
if (countAmountPair.Category == "TotalCollected" || countAmountPair.Category == "TotalCancelled")
{
<div class="col-sm-12">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
#Html.TextBoxFor(m => m[i].Description, new { #class = "form-control", #readonly = "readonly" })
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
#Html.TextBoxFor(m => m[i].Amount, "{0:N2}", new { #class = "form-control", type = "numeric", dir = "rtl", #readonly = "readonly" })
</div>
</div>
</div>
</div>
}
else
{
<div class="col-sm-12">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
#Html.TextBoxFor(m => m[i].Count, "{0:N0}", new { #class = "form-control", type = "numeric", dir = "rtl", #readonly = "readonly" })
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
#Html.TextBoxFor(m => m[i].Amount, "{0:N2}", new { #class = "form-control", type = "numeric", dir = "rtl", #readonly = "readonly" })
</div>
</div>
</div>
</div>
}
}
I have below form which is of method=get.
#using (Html.BeginForm("Search", "Home", FormMethod.Get, htmlAttributes: new { #class = "main-search", id = "frmsearch", role = "form" })) {
<div class="row">
<div class="col-md-3 col-sm-3">
<div class="form-group">
<label for="type">Property Type</label>
#Html.ListBoxFor(m => m.searchModel.CategoriesId, Model.searchModel.Categories, htmlAttributes: new { id = "type", multiple = "multiple", #class = "animate", data_transition_parent = ".dropdown-menu", title = "All" })
</div>
<!-- /.form-group -->
</div>
<div class="col-md-3 col-sm-3">
<div class="form-group">
<label for="location">Location</label>
#Html.DropDownListFor(m => m.searchModel.LocationID, Model.searchModel.Locations, htmlAttributes: new { id = "location", multiple = "multiple", #class = "animate", data_transition_parent = ".dropdown-menu", title = "All" })
</div>
<!-- /.form-group -->
</div>
<div class="col-md-3 col-sm-3">
<div class="form-group">
<label>Status</label>
#Html.DropDownListFor(m => m.searchModel.StatusID, Model.searchModel.Status, htmlAttributes: new { id = "status", multiple = "multiple", #class = "animate", data_transition_parent = ".dropdown-menu", title = "All" })
</div>
<!-- /.form-group -->
</div>
<div class="col-md-2 col-sm-3">
<div class="form-group">
<label>Price</label>
<div class="ui-slider" id="price-slider-category" data-value-min="#Model.searchModel.MinPrice" data-value-max="#Model.searchModel.MaxPrice" data-value-type="price" data-currency="₹" data-currency-placement="before">
<div class="values clearfix">
#Html.TextBoxFor(m => m.searchModel.MinPrice, htmlAttributes: new { id = "value-min", #class = "value-min", name = "value-min[]", #readonly = "readonly", style = "padding:0px" })
#Html.TextBoxFor(m => m.searchModel.MaxPrice, htmlAttributes: new { id = "value-max", #class = "value-max", name = "value-max[]", #readonly = "readonly", style = "padding:0px" })
</div>
<div class="element"></div>
</div>
</div>
<!-- /.form-group -->
</div>
<div class="col-md-1 col-sm-3">
<div class="form-group">
<label></label>
<button type="submit" style="color:white" id="searchSubmit" class="btn btn-block blue waves-effect">
<i class="fa fa-search"> </i>
</button>
</div>
<!-- /.form-group -->
</div>
<!--/.col-md-6-->
</div>
<!--/.row-->
}
and I have this JS to post form values through AJAX
$(document).on('click', '#searchSubmit', function (e) {
var _form = $(this).closest('form');
var _url = _form.attr('action');
var formData = _form.serialize();
var request = $.get(_url, formData);
request.complete(function (response) {
})
})
Here is my model
public class SearchFilters
{
public SearchFilters()
{
MinPrice = 10000;
MaxPrice=8000000;
}
public IEnumerable<SelectListItem> Categories { get; set; }
public int[] CategoriesId { get; set; }
public IEnumerable<SelectListItem> Locations { get; set; }
public int[] LocationID { get; set; }
public IEnumerable<SelectListItem> Status { get; set; }
public int[] StatusID { get; set; }
public int MinPrice { get; set; }
public int MaxPrice { get; set; }
}
and this is my controller method to process the search request.
[HttpGet]
public ActionResult Search([Bind(Prefix = "searchModel")]SearchFilters smodel)
{
ProjectsViewModel model = new ProjectsViewModel();
//search db and fill model
return PartialView("_PropertyDetails", model);
}
The UI rendering happens for min and max value using noUiSlider plugin and thus inputs are readonly but gets updated through update option of noUiSlider. But whenever model is received in Server it comes as default value assigned to model variables even after update. The values doesn't get updated when inspected in DOM but its reflected in UI. Yes it is because of readonly property of textbox but Is there any other way to post the readonly property values in these type of situations? Below are few screenshots of how UI looks and DOM and model values when it is received.
UI
DOM
Model
UPDATE
I can see the posted values in URL as ...searchModel.MinPrice=₹2%2C189%2C090.00&searchModel.MaxPrice=₹5%2C772%2C480.00 But not in model. Not sure how to get on this..
₹ and , formatting makes the MinPrice and MaxPrice as strings. And as a result those are not getting bind to int properties. Just remove the formatting and send them in GET, then they will be getting bind to int properties.
I want to add input to form dynamically with jQuery templates.
My viewModel for rendering form is listed below
public class FormViewModel
{
public int Id { get; set; }
[Required]
[StringLength(25, ErrorMessage = "Max firstname length is 25 symbols.")]
[DisplayName("First name")]
public string FirstName { get; set; }
[Required]
[StringLength(25, ErrorMessage = "Max lastname length is 25 symbols.")]
[DisplayName("Last name")]
public string LastName { get; set; }
[Required]
[Email(ErrorMessage = "Provide correct email address, please.")]
[DisplayName("Email")]
public string Email { get; set; }
[Range(16, 150, ErrorMessage = "Age should be between 16 and 150.")]
[DisplayName("Age")]
public int? Age { get; set; }
public IList<DiscountCode> Discounts { get; set; }
}
This is my model which I use for inputs that will be created dynamically.
public class DiscountCode
{
[Required]
[DisplayName("Code name")]
[StringLength(10, ErrorMessage = "Max name length is 10 symbols.")]
public string Code { get; set; }
[Required]
[DisplayName("Code discount")]
[Integer(ErrorMessage = "The field Percent should be a positive non-decimal number")]
[Range(1,60, ErrorMessage = "The field Percent should be between 1 and 60.")]
public int Percent { get; set; }
}
I have this partial view for rendering DiscountCode inputs
#using DynamicForm.Models
#model FormViewModel
#if (Model != null && Model.Discounts != null)
{
for (int i = 0; i < Model.Discounts.Count; i++)
{
<div class="row">
<input type="hidden" name="Discounts.Index" value="#i" />
<div class="col-md-4 form-group">
<div class="input-group">
#Html.TextBoxFor(m => m.Discounts[i].Code, new { #class = "form-control " })
#Html.ValidationMessageFor(m => m.Discounts[i].Code, string.Empty, new { #class = "help-block" })
</div>
</div>
<div class="col-md-6 form-group">
<div class="input-group">
#Html.LabelFor(m => m.Discounts[i].Percent, new { #class = "control-label" })
#Html.TextBoxFor(m => m.Discounts[i].Percent, new { #class = "form-control " })
#Html.ValidationMessageFor(m => m.Discounts[i].Percent, string.Empty, new { #class = "help-block" })
</div>
</div>
<div class="col-md-2 form-group">
<div class="input-group">
<button type="button" class="btn btn-primary removeDiscountRow">Remove</button>
</div>
</div>
</div>
}
}
And for adding discount inputs I use this code snippet
var data = { index: lastIndex };
var html = $.templates("#discountRow").render(data);
$(html).appendTo($discountsContainer);
and this template
<script id="discountRow" type="text/x-jsrender">
<div class="row">
<input type="hidden" name="Discounts.Index" value="{{: index}}">
<div class="col-md-4 form-group">
<div class="input-group">
<label class="control-label" for="Discounts_{{: index}}__Code">Code name</label>
<input class="form-control " data-val="true" data-val-required="Code is required" data-val-length="Max name length is 10 symbols." data-val-length-max="10"
id="Discounts_{{: index}}__Code" name="Discounts[{{: index}}].Code" type="text" value="">
<span class="field-validation-valid help-block" data-valmsg-for="Discounts[{{: index}}].Code" data-valmsg-replace="true"></span>
</div>
</div>
<div class="col-md-6 form-group">
<div class="input-group">
<label class="control-label" for="Discounts_{{: index}}__Percent">Code discount</label>
<input class="form-control " data-val="true" data-val-required="Percent is required" data-val-number="The field Code discount must be a number."
data-val-range="The field Percent should be between 1 and 60." data-val-range-max="60" data-val-range-min="1"
data-val-regex="The field Percent should be a positive non-decimal number."
data-val-regex-pattern="^-?\d+$" data-val-required="The Code discount field is required."
id="Discounts_{{: index}}__Percent" name="Discounts[{{: index}}].Percent" type="text" value="0" aria-required="true" aria-invalid="false"
aria-describedby="Discounts_{{: index}}__Percent-error">
<span class="help-block field-validation-valid" data-valmsg-for="Discounts[{{: index}}].Percent" data-valmsg-replace="true"></span>
</div>
</div>
<div class="col-md-2 form-group">
<div class="input-group">
<button type="button" class="btn btn-primary removeDiscountRow">Remove</button>
</div>
</div>
</div>
</script>
As you can see I just copy output of razor and insert it in template. So if I change validation in model I'll change template each time. How to generate this template automatic with preserving all data attributes for client-side validation ?
You can generate templte code like you create your input code, but Model.Discounts must have at least one element. See code below. I add DiscountCode to discounts if its empty and change some html attributes to make template display as you want;)
if (Model.Discounts == null || Model.Discounts.Count <= 0)
{
Model.Discounts = new List<DiscountCode> { new DiscountCode() };
}
<script id="discountRow" type="text/x-jsrender">
<div class="row">
<input type="hidden" name="Discounts.Index" value="{{: index}}" />
<div class="col-md-4 form-group">
<div class="input-group">
#Html.LabelFor(m => m.Discounts[0].Percent, new { #class = "control-label", For = "Discounts[{{: index}}].Code" })
#Html.TextBoxFor(m => m.Discounts[0].Code, new { #class = "form-control ", Id = "Discounts_{{: index}}__Code", Name = "Discounts[{{: index}}].Code", Value="" } )
#Html.ValidationMessageFor(m => m.Discounts[0].Code, string.Empty, new { #class = "help-block", Data_Valmsg_For = "Discounts[{{: index}}].Code" })
</div>
</div>
<div class="col-md-6 form-group">
<div class="input-group">
#Html.LabelFor(m => m.Discounts[0].Percent, new { #class = "control-label", For = "Discounts[{{: index}}].Percent" })
#Html.TextBoxFor(m => m.Discounts[0].Percent, new { #class = "form-control ", Id = "Discounts_{{: index}}__Percent", Name = "Discounts[{{: index}}].Percent", Value = "" })
#Html.ValidationMessageFor(m => m.Discounts[0].Percent, string.Empty, new { #class = "help-block", Data_Valmsg_For = "Discounts[{{: index}}].Percent" })
</div>
</div>
<div class="col-md-2 form-group">
<div class="input-group">
<button type="button" class="btn btn-primary removeDiscountRow">Remove</button>
</div>
</div>
</div>
</script>