upload image in server folder and save path in Sqlserver using entity framework mvc4 - asp.net-mvc

I am trying to save picture in folder and store path in Sqlserver 2008 using entity framework. I need register the user with picture. My code is saving all the data in database except picture and picture path.
My model is
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public partial class customer
{
[Display(Name="Username")]
public string user_id { get; set; }
[Display(Name = "Password")]
public string password { get; set; }
[Display(Name = "First Name")]
public string first_name { get; set; }
[Display(Name = "Last Name")]
public string last_name { get; set; }
[Display(Name = "Address")]
public string address { get; set; }
[Display(Name = "City")]
public string city { get; set; }
[Display(Name = "State")]
public string state { get; set; }
[Display(Name = "Zip")]
public Nullable<int> zip { get; set; }
[Display(Name = "Country")]
public string country { get; set; }
[Display(Name = "Email Address")]
public string email { get; set; }
[Display(Name = "Phone")]
public string phone { get; set; }
[Display(Name = "Picture")]
public string picture { get; set; }
[Display(Name = "Registration Date")]
public Nullable<System.DateTime> reg_date { get; set; }
[Display(Name = "Status")]
public string status { get; set; }
[Display(Name = "Keep me logged in")]
public bool rememberme { get; set; }
}
}
My Controller is
[HttpPost]
public ActionResult Register(customer customer, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
if (file != null)
{
file.SaveAs(HttpContext.Server.MapPath("~/image/") + file.FileName);
customer.picture = file.FileName;
}
onlinebookstoreEntities1 db = new onlinebookstoreEntities1();
db.customers.Add(customer);
db.SaveChanges();
return RedirectToAction("Index","Home");
}
return View(customer);
}
and my view is
#using (Html.BeginForm("Register", "Account", FormMethod.Post, new { enctype = "multipart/form-data" })) {
<div class="editor-label">
#Html.LabelFor(model => model.first_name)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.first_name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.last_name)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.last_name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.user_id)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.user_id)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.password)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.password)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.address)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.address)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.city)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.city)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.state)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.state)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.zip)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.zip)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.country)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.country)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.email)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.email)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.phone)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.phone)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.picture)
</div>
<div class="btnreg">
<input type="file" id="picture" value="Upload Picture" />
</div>
<div class="txtreg">
#Html.CheckBoxFor(model => model.rememberme) #Html.LabelFor(model => model.rememberme)
</div>
<input type="submit" value="Create Account" name="btnsub" />
}

If you want to save a picture in the database your property have to look like this:
[DisplayName("Billede")]
[MaxLength]
public byte[] PhotoFile { get; set; }
and not:
[Display(Name = "Picture")]
public string picture { get; set; }
You save your picture like this:
#using (Html.BeginForm("Create", "Photo", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.DisplayNameFor(model => model.PhotoFile)
<input type="file" name="Image" />
And the ActionResult method inside your PhotoController would be
public ActionResult Create(Photo photo, HttpPostedFileBase image)
{
and the actual saving of the photo itself
if (image != null)
{
photo.ImageFileName = image.FileName;
photo.ImageMimeType = image.ContentType;
photo.PhotoFile = new byte[image.ContentLength];
image.InputStream.Read(photo.PhotoFile, 0, image.ContentLength);
}
context.Add<Photo>(photo);
context.SaveChanges();
Hope you can connect the dots.
Mohammad

check your image folder permissions, If not, set it to all read, write, execute permissions. Try to debug the code and check whether the file is null or any exception fires while file.SaveAs called

Saving url into db is quite simple.At the same time you can save the picture in byte format in db.In your customer model you have
Method-1:
Change string type or any other type to byte.
So In this picture if you want to save the picture you convert picture to byte type instead of string in your customer table in db.
//before
[Display(Name = "Picture")]
public string picture { get; set; }
//After changing in db you add the table in entity framework .edmx and now it becomes
[Display(Name = "Picture")]
public byte[] picture { get; set; }
Here follows your code to save picture in byte format in db.
In your controller
public ActionResult Register(customer model)
{
string ImageName = Path.GetFileName(file.FileName);
string physicalPath = Server.MapPath("~/images/" + ImageName);
file.SaveAs(physicalPath);
customer newRecord = new customer ();
newRecord.username= customer.username;
\\Assign for remaining feilds in table in this way.
using (MemoryStream ms = new MemoryStream())
{
file.InputStream.CopyTo(ms);
byte[] picArray = ms.GetBuffer();
newRecord.picture= picArray ;
}
onlinebookstoreEntities1 db = new onlinebookstoreEntities1();
db.customers.Add(newRecord);
db.SaveChanges();
}
In your Register View
<div>
#using (Html.BeginForm("ConfigAssetData", "Home", new { #tabno = "3" }, FormMethod.Post, new { enctype = "multipart/form-data", #class = "form-horizontal" }))
{
<div class="editor-label">
#Html.LabelFor(model => model.first_name)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.first_name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.last_name)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.last_name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.user_id)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.user_id)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.password)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.password)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.address)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.address)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.city)
</div>
<div class="txtreg">
#Html.EditorFor(model => model.city)
</div>
#*UploadFile*#
**<input type="file" class="file-input" name="file"/>**
#*Similar code here...*#
}
</div>
Method-2:
Especially in your case as you need to save picture path what you all need to do is:-
In your Controller
public ActionResult Register(customer model)
{
string ImageName = Path.GetFileName(file.FileName);
string physicalPath = Server.MapPath("~/images/" + ImageName);
file.SaveAs(physicalPath);
customer newRecord = new customer ();
newRecord.username= customer.username;
//.......saving picture url......
newRecord.picture = physicalPath;
//Assign for remaining feilds in table in this way.
onlinebookstoreEntities1 db = new onlinebookstoreEntities1();
db.customers.Add(newRecord);
db.SaveChanges();
}
If you right click on your images folder and click "Open folder in windows explorer" you can see your pic uploaded.

Related

How to save to database Client IP Address of Visitors Machine in ASP.Net MVC?

am trying to get IP Address of client Machine Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; it's working fine.
Get IP On page load
public ActionResult AddCompany()
{
get_IP();
return View();
}
get_IP code
public void get_IP()
{
string ipAddress = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(ipAddress))
{
ipAddress = Request.ServerVariables["REMOTE_ADDR"];
}
ViewBag.IPAddress = ipAddress;
}
But when user register the form get IP address value also save in the data base..
Cs.html File
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<h1 class="page-header">Add Company</h1>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.IPAddress)
<div class="form-group">
#Html.LabelFor(model => model.CompanyName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CompanyName)
#Html.ValidationMessageFor(model => model.CompanyName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ShortName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ShortName)
#Html.ValidationMessageFor(model => model.ShortName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Email, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Country, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#*#Html.EditorFor(model => model.Country)*#
#Html.DropDownList("Country", null, "---Select Country----")
#Html.ValidationMessageFor(model => model.Country)
</div>
</div>
<div class="form-group">
<b>State: </b>
<select id="state"></select><br />
</div>
<div>
<b>City: </b>
<select id="city"></select><br />
</div>
<div class="form-group">
#Html.LabelFor(model => model.MobileNo, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.MobileNo)
#Html.ValidationMessageFor(model => model.MobileNo)
</div>
</div>
<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>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
</div>
I create one #Html.HiddenFor(model => model.IPAddress) hidden filed value but it's not working ..
On page load IPAddress Value is showing .after i click to save button the Ip value is not saved to the database..
AddCompany
[HttpPost]
public ActionResult AddCompany(Company cmp)
{
using (DataContext entities = new DataContext())
{
entities.Company.Add(cmp);
entities.SaveChanges();
int id = cmp.CompanyID;
Session.Clear();
Response.Redirect("Index");
}
return View(cmp);
}
Any idea How to save client IP Adrress from the database..
Class File
[Table("MySecondMVCDemo")]
public class Company
{
[Key]
public int CompanyID { get; set; }
[Required(ErrorMessage = "Please Enter Company Name")]
[Display(Name = "CompanyName")]
public string CompanyName { get; set; }
[Required(ErrorMessage = "Please Enter Short Name")]
[Display(Name = "ShortName")]
public string ShortName { get; set; }
[Required(ErrorMessage = "Please Enter Email Address")]
[Display(Name = "Email")]
public string Email { get; set; }
[Required(ErrorMessage = "Please Enter Email Address")]
[Display(Name = "Country")]
public string Country { get; set; }
[Required(ErrorMessage = "Please Enter Mobile No")]
[Display(Name = "MobileNo")]
public string MobileNo { get; set; }
public Int32? IPAddress { get; set; }
}
I do not know about HiddenFor because I have not use it before.
How I hid fields before was like this:
#Html.TextBoxFor(model => model.IPAddress, new { #class = "sr-only", #type = "hidden" })
You can add the bootstrap class sr-only to make sure it is hidden.
Make sure you check your browser inspector to see whether the hidden field has a value.
If posted and is still not saving, then try to assign the IpAddress identity to the form field value before saving it like this:
cmp.IPAddress = Request.Form["IPAddress"];
Store IP address as a string instead of Int32
Please use code from here to get IP Address
http://tutorialgenius.blogspot.in/2010/09/aspnet-get-ipv4-address-even-if-user-is.html

DropDownListFor in MVC 4

I am having a hard time to show dropdownlist for in the view, the values will be populated from database. I am using MS SQL Server as the database.
I want to show a drop down list in ApplyingFor which will be populated from database.
Please help me out.
This is the Model
public class CandidateProfile
{
[Display(Name = "Candidate Name")]
[Required(ErrorMessage = "Provide a Name", AllowEmptyStrings=false)]
[DataType(DataType.Text)]
public string CandidateName { get; set; }
[Required(ErrorMessage = "Provide Your Address",AllowEmptyStrings = false)]
[Display(Name = "Address")]
[DataType(DataType.MultilineText)]
public string Address { get; set; }
[Display(Name = "Phone Number")]
[Required(ErrorMessage = "Provide a Phone Number")]
[RegularExpression("^([07][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | 8[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | 9[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])$", ErrorMessage = "Enter Valid Mobile Number")]
public string PhoneNumber { get; set; }
[Display (Name = "Email-Id")]
[Required(ErrorMessage="Provide an email-id")]
[EmailValidator]
public string EmailId { get; set; }
[Display (Name = "Applying For")]
public string **ApplyingFor** { get; set; }
[Display (Name = "Experience")]
[Required(ErrorMessage = "")]
public int Experience { get; set; }
[Display (Name = "Present Location")]
[Required(ErrorMessage = "")]
public string PresentLocation { get; set; }
}
public class ApplyingPositions
{
public IEnumerable<ApplyingPositions> ApplyingPosition { get; set; }
}
public class ApplyingPosition
{
public int APId { get; set; }
public string Designation { get; set; }
}
This is the View:
#model Recruitment.Models.CandidateProfile
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>CandidateProfile</legend>
<div class="editor-label">
#Html.LabelFor(model => model.CandidateName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CandidateName)
#Html.ValidationMessageFor(model => model.CandidateName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Address)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Address)
#Html.ValidationMessageFor(model => model.Address)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PhoneNumber)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PhoneNumber)
#Html.ValidationMessageFor(model => model.PhoneNumber)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.EmailId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.EmailId)
#Html.ValidationMessageFor(model => model.EmailId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ApplyingFor)
<div class="editor-field">
#Html.EditorFor(model => model.ApplyingFor)
#Html.ValidationMessageFor(model => model.ApplyingFor)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Experience)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Experience)
#Html.ValidationMessageFor(model => model.Experience)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PresentLocation)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PresentLocation)
#Html.ValidationMessageFor(model => model.PresentLocation)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
You need to pass the List of Options from your controller to view. So, before returning View
var listOfPositions = new List<ApplyingPosition>();
listOfPositions = //Call the service to populate the listOfPositions from Database here
ViewBag.PositionsList = new SelectList(listOfPositions, "APId", "Designation");
In your view instead of #Html.EditorFor(model => model.ApplyingFor)
#Html.DropDownListFor(m => m.ApplyingFor, (SelectList)ViewBag.PositionsList, "Select")
populate lstApplyingFor (list) form your DB. and in your controller
ViewBag.ApplyingFor = new SelectList(lstApplyingFor, "Id", "Name");
and in view:-
#Html.DropDownList(m => m.ApplyingFor,"ApplyingFor", "--Select--")
First-
1) You need to create the source for dropdown as-
var listForApplyingFor= db.Table.Select(o=> new SelectListItem{
Value=o.ID,
Text= o.Text
}).ToList();
ViewBag.ItemsApplyingFor= listForApplyingFor
.Cshtml View-
#Html.DropdownListFor(m=>m.ApplyingFor, new SelectList(ViewBag.ItemsApplyingFor,"Value","Text"),"Select...", htmlAttributes:new{ })
Let me know if it helps.

POST Method doesn't work MVC 4

I try Create a new article in my table art, but the POST Method doesn't work, i don't now why, , Edit Article working perfectly, i read many post form that topic and nothing, i hope anyone can help me
Model
public class Art
{
[Key]
public int idArt { get; set; }
[DisplayName("Codigo Artículo")]
[Required(ErrorMessage = "Codigo Artículo Requerido")]
[MaxLength(30)]
public string co_art { get; set; }
[DisplayName("Tipo Articulo")]
[ForeignKey("TypeArticles")]
[Required(ErrorMessage = "Tipo Artículo Requerido")]
public int IDType { get; set; }
public virtual TypeArticles TypeArticles { get; set; }
[DisplayName("Descripción")]
[Required(ErrorMessage = "Descripción Artículo Requerido")]
[MaxLength(150)]
public string des_art { get; set; }
[DisplayName("Modelo")]
[Required(ErrorMessage = "Modelo Artículo Requerido")]
[MaxLength(50)]
public string modelo { get; set; }
[DisplayName("Referencia")]
[MaxLength(50)]
[Required(ErrorMessage = "Referencia Artículo Requerido")]
public string referencia { get; set; }
[DisplayName("Linea Artículo")]
[ForeignKey("Linea")]
[Required(ErrorMessage = "Linea Artículo Requerido")]
public int IdLinea { get; set; }
public virtual Linea Linea { get; set; }
[DisplayName("Categoria Artículo")]
[ForeignKey("Categoria")]
[Required(ErrorMessage = "Categoria Artículo Requerido")]
public int idCat { get; set; }
public virtual Categoria Categoria { get; set; }
[DisplayName("Precio Venta")]
[Range(0.01, 999999999, ErrorMessage = "Precio debe estar entre 0.01 y 999999999")]
public double Price { get; set; }
[MaxLength(1024)]
[DisplayName("Info. Adicional")]
public string Adicional { get; set; }
[MaxLength(100)]
public string Photo { get; set; }
}
Controller POST Method
[HttpPost]
[ValidateInput(false)]
public ActionResult Create(Art artmodels)
{
ViewBag.idLinea = new SelectList(db.Linea.OrderBy(c => c.des_lin), "IdLinea", "des_lin");
ViewBag.IdCat = new SelectList(db.Categorias.OrderBy(c => c.des_cat), "IdCat", "des_cat");
ViewBag.IDType = new SelectList(db.TypeArticles.OrderBy(c => c.TypeDesc), "IDType", "TypeDesc");
if (ModelState.IsValid)
{
var art_exists = (from inv in db.Art where inv.co_art == artmodels.co_art.Trim() select inv).FirstOrDefault();
if (art_exists != null)
{
ModelState.AddModelError("co_art", "Codigo de Articulo ya Existe");
return View(artmodels);
}
db.Art.Add(artmodels);
db.SaveChanges();
///
//int currentPageIndex = page.HasValue ? page.Value - 1 : 0;
//var articulos = db.Art;
//IPagedList<Art> art_paged = null;
//art_paged = articulos.OrderBy(i => i.co_art).ToPagedList(currentPageIndex, (pagesize.HasValue) ? pagesize.Value : defaultPageSize);
return RedirectToAction("Edit", "Articulos", new {id = artmodels.idArt });
}
this.Response.StatusCode = 400;
return View(artmodels);
}
View
#model mvcAmerica.Models.Art
#{
ViewBag.Title = "Creacion";
}
<h1><small>Creación Articulos</small></h1>
#using (Html.BeginForm("Create", "Articulos", FormMethod.Post))
{
#Html.ValidationSummary(true)
<text>
#{Html.RenderPartial("CreateOrEditArticulos", Model);}
</text>
}
RenderPartial
#model mvcAmerica.Models.Art
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
#Html.HiddenFor(model => model.idArt)
<div class="clearfix">
#Html.LabelFor(model => model.co_art)
<div class="input">
#Html.EditorFor(model => model.co_art)
#Html.ValidationMessageFor(model => model.co_art)
</div>
</div>
<div class="clearfix">
#Html.LabelFor(model => model.des_art)
<div class="input">
#Html.EditorFor(model => model.des_art)
#Html.ValidationMessageFor(model => model.des_art)
</div>
</div>
<div class="clearfix">
#Html.LabelFor(model => model.IDType, "Tipo Articulo")
<div class="input chosen-select">
#Html.DropDownList("IDType", String.Empty)
#Html.ValidationMessageFor(model => model.IDType)
</div>
</div>
<div class="clearfix">
#Html.LabelFor(model => model.modelo)
<div class="input">
#Html.EditorFor(model => model.modelo)
#Html.ValidationMessageFor(model => model.modelo)
</div>
</div>
<div class="clearfix">
#Html.LabelFor(model => model.referencia)
<div class="input">
#Html.EditorFor(model => model.referencia)
#Html.ValidationMessageFor(model => model.referencia)
</div>
</div>
<div class="clearfix">
#Html.LabelFor(model => model.IdLinea)
<div class="input chosen-select">
#Html.DropDownList("IdLinea", String.Empty)
#Html.ValidationMessageFor(model => model.IdLinea)
</div>
</div>
<div class="clearfix">
#Html.LabelFor(model => model.idCat)
<div class="input chosen-select">
#Html.DropDownList("IdCat", String.Empty)
#Html.ValidationMessageFor(model => model.idCat)
</div>
</div>
<div class="clearfix">
#Html.LabelFor(model => model.Price)
<div class="input">
#Html.EditorFor(model => model.Price)
#Html.ValidationMessageFor(model => model.Price)
</div>
</div>
<div class="clearfix">
#Html.LabelFor(model => model.Adicional)
<div class="input">
#Html.EditorFor(model => model.Adicional)
#Html.ValidationMessageFor(model => model.Adicional)
</div>
</div>
<div class="actions">
<input type="submit" class="btn primary" value="Guardar" />
#Html.ActionLink("Listado", "Index", null, new { #class = "btn" })
</div>
</fieldset>
}
Thanks for the help that bring me in this problem...
You have nested forms in your code which is causing this issue. The Submit button is in the inner but it dies not have any Controller and Anction methods to call, So it's not post the data to any method.
So you need to change this code something like this:
View
#model mvcAmerica.Models.Art
#{
ViewBag.Title = "Creacion";
}
<h1><small>Creación Articulos</small></h1>
//the commented line should go to the partial view
//#using (Html.BeginForm("Create", "Articulos", FormMethod.Post))
//{
// #Html.ValidationSummary(true)
<text>
#{Html.RenderPartial("CreateOrEditArticulos", Model);}
</text>
RenderPartial
#model mvcAmerica.Models.Art
#using (Html.BeginForm("Create", "Articulos", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
// rest of the code is as it is
}

ASP Net MVC - Forms Validation on the ViewModel

I have a form which has a ViewModel class underlaying it. I have set the [Required] validation on fields of the form. The form still submits even though it does for a moment - before it submits - displays the ErrorMessage set on particular fields.
There is no validation on the StockReceipt model itself, but only the ViewModel. I looked at this question here and learnt that validating the model is optional.
I wonder why the form still submits when there are invalid input?
Here is my View and ViewModel code:
View:
#using (Html.BeginForm("SaveSettings", "StockReceipt", FormMethod.Post,
new { id = "StockReceiptForm", enctype = "multipart/form-data" }))
{
<fieldset>
<div>
#* #Html.ValidationSummary(false)*#
<legend>Stock-Receipt Details</legend>
#*#if (User.IsInRole(Constants.Super))
{*#
<div style="display: none;">
Delivery Note Ref
</div>
<div style="display: none;">
#Html.TextBoxFor(model => model.StockReceiptID, new { #Class = "k-textbox" })
</div>
<div class="editor-label">
Supplier
</div>
<div class="editor-field">
#Html.Kendo().DropDownListFor(model => model.SupplierID).BindTo(Model.SuppliersList).DataTextField("Name").DataValueField("SupplierID").OptionLabel("Select")
#Html.ValidationMessageFor(model => model.SupplierID)
</div>
<div class="editor-label">
Material
</div>
<div class="editor-field">
#Html.Kendo().DropDownListFor(model => model.MaterialID).BindTo(Model.MaterialsList).DataTextField("Name").DataValueField("MaterialID").OptionLabel("Select")
#Html.ValidationMessageFor(model => model.MaterialID)
</div>
<div class="editor-label">
Qty
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Quantity, new { #Class = "k-textbox" })
#Html.ValidationMessageFor(model => model.Quantity)
</div>
<div class="editor-label">
Of which reserved
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.QuantityReserved, new { #Class = "k-textbox" })
</div>
<div class="editor-label">
Units
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.NumberOfUnits, new { #Class = "k-textbox" })
#(Html.Kendo().DropDownListFor(model => model.StockUnitsEnum).Name("StockUnitsEnum")
.BindTo(Enum.GetValues(typeof(StockUnitsEnum))
.Cast<StockUnitsEnum>()
.Select(p => new SelectListItem
{
Text = p.ToString(),
Value = ((int)p).ToString(CultureInfo.InvariantCulture)
})
.ToList())
)
#Html.ValidationMessageFor(model => model.NumberOfUnits)
</div>
<div class="editor-label">
Batch Reference:
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.BatchReference, new { #Class = "k-textbox" })
#Html.ValidationMessageFor(model => model.BatchReference)
</div>
<div class="editor-label">
Slab Width
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.SlabWidth, new { #Class = "k-textbox" }) x #Html.TextBoxFor(model => model.SlabHeight, new { #Class = "k-textbox" })
</div>
<div class="editor-label">
Include Transport:
</div>
<div class="editor-field">
#Html.CheckBoxFor(model => model.IncludeTransport)
</div>
<div class="editor-label">
Notes
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.Notes, new { #Class = "k-textbox" })
</div>
<div class="clear">
Totals
</div>
<div class="editor-label">
Unit Cost
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.UnitCost, new { #Class = "k-textbox" })
#Html.ValidationMessageFor(model => model.UnitCost)
</div>
<div class="editor-label">
Units
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.NumberOfUnits, new { #Class = "k-textbox" })
#Html.ValidationMessageFor(model => model.NumberOfUnits)
</div>
<div class="editor-label">
Slab Cost
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.SlabCost, new { #Class = "k-textbox" })
#Html.ValidationMessageFor(model => model.SlabCost)
</div>
<div class="editor-label">
Location
</div>
<div class="editor-field">
#Html.Kendo().DropDownListFor(model => model.LocationID).BindTo(Model.LocationsList).DataTextField("Name").DataValueField("LocationID").OptionLabel("Select")
</div>
<div class="editor-label">
Purchase-Order Ref.
</div>
<div class="editor-field">
#Html.Kendo().DropDownListFor(model => model.PurchaseOrderID).BindTo(Model.PurchaseOrdersList).DataTextField("PONumber").DataValueField("PurchaseOrderID").OptionLabel("Select")
#Html.ValidationMessageFor(model => model.PurchaseOrdersList)
</div>
<div class="editor-label">
Invoice Ref.
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.InvoicNo, new { #Class = "k-textbox" })
#Html.ValidationMessageFor(model => model.InvoicNo)
</div>
<br />
<div class="editor-label">
</div>
<div class="editor-field">
<input type="submit" value="Save" class="k-button" />
</div>
</div>
</fieldset>
}
ViewModel:
public class StockReceiptViewModel
{
public int StockReceiptID { get; set; }
[Required(ErrorMessage = "Required")]
public int SupplierID { get; set; }
[Required(ErrorMessage = "Required")]
public int MaterialID { get; set; }
[Required(ErrorMessage = "Required")]
public DateTime? ReceiptDate { get; set; }
[Required(ErrorMessage = "Required")]
public int Quantity { get; set; }
public int? QuantityReserved { get; set; }
[Required(ErrorMessage = "Required")]
public decimal? SlabWidth { get; set; }
[Required(ErrorMessage = "Required")]
public decimal? SlabHeight { get; set; }
[Required(ErrorMessage = "Required")]
public int SizeUnits { get; set; }
[Required(ErrorMessage = "Required")]
public StockUnitsEnum StockUnitsEnum
{
get {return (StockUnitsEnum)SizeUnits;}
set {SizeUnits = (int)value;}
}
[Required(ErrorMessage = "Required")]
public string BatchReference { get; set; }
[Required(ErrorMessage = "Required")]
[DataType(DataType.Currency)]
public decimal? UnitCost { get; set; }
[Required(ErrorMessage = "Required")]
public int? NumberOfUnits { get; set; }
[Required(ErrorMessage = "Required.")]
public int PurchaseOrderID { get; set; }
[Required(ErrorMessage = "Required")]
public string InvoicNo { get; set; }
[Required(ErrorMessage = "Required")]
public decimal SlabCost { get; set; }
public bool IncludeTransport { get; set; }
[Required(ErrorMessage = "Required.")]
public int LocationID { get; set; }
public int? EnteredBy { get; set; }
public DateTime OnSystemFrom { get; set; }
public string Notes { get; set; }
public List<SupplierViewModel> SuppliersList { get; set; }
public List<MaterialViewModel> MaterialsList { get; set; }
public List<LocationsViewModel> LocationsList { get; set; }
public List<PurchaseOrderViewModel> PurchaseOrdersList { get; set; }
public int LastModifiedBy { get; set; }
public DateTime LastModifiedDate { get; set; }
public int LiveQuantity { get; set; }
}
The Controller method has the ModelState.Isvalid check as well.
Please help if you can.
Many thanks.
You need to add jquery.unobtrusive and jquery.validate files to your views. Add this to your BundleConfig.cs:
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.unobtrusive*",
"~/Scripts/jquery.validate*"));
And then render it on your _Layout View or in View you want validation:
#Scripts.Render("~/bundles/jqueryval")
If you are using default MVC template you should already have this bundle. Just make sure you have reference in your Views. You can check if your js files are loaded by using some web development tools like Firebug in Mozzila or press F12 in Chrome, and in NET tab you can see loaded scripts.
I have solved this problem by making sure that the method to where this form is submitting, is returning the viewmodel to the page (view) if ModelState.IsValid is false.
This is provided that the viewModel being returned is actually the same as the submitted one:
[HttpPost]
public ActionResult SaveSettings(StockReceiptViewModel stockReceiptVm)
{
try
{
if (ModelState.IsValid)
{
var stockReceipt = new StockReceipt();
if (stockReceiptVm.StockReceiptID != 0)
{
MapViewModelToModel(stockReceiptVm, stockReceipt);
stockReceipt.LastModifiedBy = UserHelper.GetCurrentUserIDByEmail();
stockReceipt.LastModifiedDate = DateTime.Now;
//update
_stockReceiptRepository.UpdateStockReceipt(stockReceipt, stockReceiptVm.StockReceiptID);
}
else
{
MapViewModelToModel(stockReceiptVm, stockReceipt);
stockReceipt.EnteredBy = UserHelper.GetCurrentUserIDByEmail();
stockReceipt.OnSystemFrom = Utilities.RemoveTimeFromDate(DateTime.Now);
//save new
_stockReceiptRepository.InsertStockReceipt(stockReceipt);
}
return RedirectToAction("Index", "StockReceiptsGrid");
}
SetupViewDropdownLists(stockReceiptVm);
return View("Index", stockReceiptVm);
}
catch (Exception exc)
{
ErrorHelper.WriteToEventLog(exc);
return RedirectToAction("Index", "Error");
}
}

EF database-first generated form won't validate

I've just created a new controller, along with its CRUD forms, etc, with a database-first EF model/entity.
Its throwing a number of validation errors on save, but since the form has validators, I don't see why this would be so.
For reasons that are beyond me, I'm not getting any validation to happen at all. It just goes right in to the saveChanges() call, which promptly fails.
Here's the edit form:
#model StatementsApplication.DAL.StatementTask
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>StatementTask</legend>
<div class="editor-label">
#Html.LabelFor(model => model.sInitials)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.sInitials)
#Html.ValidationMessageFor(model => model.sInitials)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.dtCompleted)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.dtCompleted)
#Html.ValidationMessageFor(model => model.dtCompleted)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.sGroupLabel)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.sGroupLabel)
#Html.ValidationMessageFor(model => model.sGroupLabel)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.nGroupSequence)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.nGroupSequence)
#Html.ValidationMessageFor(model => model.nGroupSequence)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.sTaskType)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.sTaskType)
#Html.ValidationMessageFor(model => model.sTaskType)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.sTaskLabel)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.sTaskLabel)
#Html.ValidationMessageFor(model => model.sTaskLabel)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.nTaskSequence)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.nTaskSequence)
#Html.ValidationMessageFor(model => model.nTaskSequence)
</div>
#Html.HiddenFor(model => model.ID)
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
and here's the generated model:
namespace StatementsApplication.DAL
{
using System;
using System.Collections.Generic;
public partial class StatementTask
{
public int StmtBatchID { get; set; }
public string sInitials { get; set; }
public Nullable<System.DateTime> dtCompleted { get; set; }
public string sGroupLabel { get; set; }
public double nGroupSequence { get; set; }
public string sTaskType { get; set; }
public string sTaskLabel { get; set; }
public double nTaskSequence { get; set; }
public int ID { get; set; }
public virtual StatementBatch tblStmtBatch { get; set; }
}
}
and here's the controller bits...
//
// GET: /StatementTask/Edit/5
public ActionResult Edit(int id = 0)
{
StatementTask statementtask = db.StatementTasks.Find(id);
if (statementtask == null)
{
return HttpNotFound();
}
ViewBag.StmtBatchID = new SelectList(db.StatementBatches, "ID", "sStatus", statementtask.StmtBatchID);
return View(statementtask);
}
//
// POST: /StatementTask/Edit/5
[HttpPost]
public ActionResult Edit(StatementTask statementtask)
{
if (ModelState.IsValid)
{
try
{
db.Entry(statementtask).State = EntityState.Modified;
db.SaveChanges();
}
catch (Exception ex) {
throw ex;
}
return RedirectToAction("Index");
}
ViewBag.StmtBatchID = new SelectList(db.StatementBatches, "ID", "sStatus", statementtask.StmtBatchID);
return View(statementtask);
}
Its a matter of some confusion for me as to why sInitials is throwing 'required' validation errors, as well as why sGroupLabel is throwing length validation errors.
Thanks
a) your model has no data validation annotations. As such, MVC doesn't do any validation, because you're not telling it what to validate.
b) You don't mention what you are submitting. Are you just submitting an empty form?
it appears that Data Annotations will resolve this issue
[Required(AllowEmptyStrings = true)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public object Note { get; set; }
via http://fendy-huang.blogspot.com/2011/04/how-to-pass-empty-string-in-entity.html

Resources