Values are null when I wanna edit DB in ASP.NET MVC - asp.net-mvc

I have a problem with my project in ASP.NET Model-View-Controller.
I have an application "Guestbook". I can successfully create guests, but I cannot edit them.
Look:
1. I start application - all ok
2. I create a guest - all ok (guest has all the entered data)
3. I click "edit" - all ok
4. I see new window. All fields on the screen have correct data, but I have a breakpoint in edit function and I see that all variables are null.
Model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
namespace Guestbook.Models
{
public class Guest
{
public int ID { get; set; }
[Display(Name = "name", ResourceType=typeof(Resources.Resources))]
[Required(ErrorMessageResourceType = typeof(Resources.Resources),
ErrorMessageResourceName = "nameRequired")]
[StringLength(50, ErrorMessageResourceType = typeof(Resources.Resources),
ErrorMessageResourceName = "nameLong")]
public string name { get; set; }
[Display(Name = "surname", ResourceType = typeof(Resources.Resources))]
[Required(ErrorMessageResourceType = typeof(Resources.Resources),
ErrorMessageResourceName = "surnameRequired")]
[StringLength(50, ErrorMessageResourceType = typeof(Resources.Resources),
ErrorMessageResourceName = "surnameLong")]
public string surname { get; set; }
[Display(Name = "firm", ResourceType = typeof(Resources.Resources))]
[Required(ErrorMessageResourceType = typeof(Resources.Resources),
ErrorMessageResourceName = "firmRequired")]
[StringLength(50, ErrorMessageResourceType = typeof(Resources.Resources),
ErrorMessageResourceName = "firmLong")]
public string firm { get; set; }
[Display(Name = "toWhom", ResourceType = typeof(Resources.Resources))]
[Required(ErrorMessageResourceType = typeof(Resources.Resources),
ErrorMessageResourceName = "toWhomRequired")]
[StringLength(50, ErrorMessageResourceType = typeof(Resources.Resources),
ErrorMessageResourceName = "toWhomLong")]
public string toWhom { get; set; }
[Display(Name = "permitNumber", ResourceType = typeof(Resources.Resources))]
[Required(ErrorMessageResourceType = typeof(Resources.Resources),
ErrorMessageResourceName = "permitRequired")]
[Range(0, 10000, ErrorMessageResourceType = typeof(Resources.Resources),
ErrorMessageResourceName = "permitRange")]
public int permitNumber { get; set; }
[Display(Name = "magazine", ResourceType = typeof(Resources.Resources))]
[Required(ErrorMessageResourceType = typeof(Resources.Resources),
ErrorMessageResourceName = "magazineRequired")]
public bool magazine { get; set; }
[Display(Name = "entranceTime", ResourceType = typeof(Resources.Resources))]
[DataType(DataType.Date)]
public DateTime? entranceTime { get; set; }
[Display(Name = "entranceTimeTime", ResourceType = typeof(Resources.Resources))]
public string entranceTimeTime { get; set; }
[Display(Name = "exitDate", ResourceType = typeof(Resources.Resources))]
[DataType(DataType.Date)]
public DateTime? exitDate { get; set; }
[Display(Name = "exitTime", ResourceType = typeof(Resources.Resources))]
public string exitTime { get; set; }
}
public class GuestDBContext : DbContext
{
public DbSet<Guest> Guests { get; set; }
}
}
Controller:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using Guestbook.Models;
namespace Guestbook.Controllers
{
public class GuestsController : BaseController
{
private GuestDBContext db = new GuestDBContext();
// GET: Guests
public ActionResult Index()
{
//Sortowanie po nazwisku.
var guests = from s in db.Guests select s;
guests = guests.OrderBy(s => s.surname);
return View(guests.ToList());
}
// GET: Guests/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Guest guest = db.Guests.Find(id);
if (guest == null)
{
return HttpNotFound();
}
return View(guest);
}
// GET: Guests/Create
public ActionResult Create()
{
return View();
}
// POST: Guests/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,name,surname,firm,toWhom,permitNumber,magazine,entranceTime,entranceTimeTime,exitDate,exitTime")] Guest guest)
{
guest.entranceTime = DateTime.Today;
guest.exitDate = DateTime.Today;
DateTime dt = DateTime.Now;
string format = "HH:mm:ss";
guest.entranceTimeTime = dt.ToString(format);
guest.exitTime = dt.ToString(format);
if (ModelState.IsValid)
{
db.Guests.Add(guest);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(guest);
}
// GET: Guests/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Guest guest = db.Guests.Find(id);
if (guest == null)
{
return HttpNotFound();
}
return View(guest);
}
// POST: Guests/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "exitDate,exitTime")] Guest g)
{
g.exitDate = DateTime.Today;
DateTime dt = DateTime.Now;
string format = "HH:mm:ss";
g.exitTime = dt.ToString(format);
if (ModelState.IsValid)
{
db.Entry(g).State = EntityState.Modified;
db.Entry(g).Property(gg => gg.name).IsModified = false;
db.Entry(g).Property(gg => gg.surname).IsModified = false;
db.Entry(g).Property(gg => gg.firm).IsModified = false;
db.Entry(g).Property(gg => gg.permitNumber).IsModified = false;
db.Entry(g).Property(gg => gg.magazine).IsModified = false;
db.Entry(g).Property(gg => gg.toWhom).IsModified = false;
db.Entry(g).Property(gg => gg.entranceTime).IsModified = false;
db.Entry(g).Property(gg => gg.entranceTimeTime).IsModified = false;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(g);
}
// GET: Guests/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Guest guest = db.Guests.Find(id);
if (guest == null)
{
return HttpNotFound();
}
return View(guest);
}
// POST: Guests/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Guest guest = db.Guests.Find(id);
db.Guests.Remove(guest);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
View:
#model Guestbook.Models.Guest
#{
ViewBag.Title = #Resources.exitGuest;
}
<h2>#Resources.exitGuest</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.ID)
<div class="form-group">
#Html.LabelFor(model => model.name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DisplayFor(model => model.name, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.surname, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DisplayFor(model => model.surname, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.firm, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DisplayFor(model => model.firm, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<br />
<div class="form-group">
<div class="col-md-10">
<b>#Resources.leftOk</b>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value=#Resources.y class="btn btn-default" />
<input type="button" value=#Resources.cancel onclick="location.href='#Url.Action("","guests")'" class="btn btn-default" />
</div>
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}

Firstly in your view you are only outputting a single form variable which is the ID parameter. All of the other model properties are being displayed only. You either need to output them as, for example, EditorFor or HiddenFor to get them posted back.
Secondly in your Edit method, the method signature is this:
public ActionResult Edit([Bind(Include = "exitDate,exitTime")] Guest g)
The Bind attribute is telling the MVC model binder to only bind the exitDate and exitTime properties so everything else will show as null. You can either remove the attribute:
public ActionResult Edit(Guest g)
Or add in the other properties that you require to be passed in:
public ActionResult Edit([Bind(Include = "exitDate,exitTime,name,surname,etc...")] Guest g)
So if you combine those two problems you will see that even the ID property isn't getting passed through and everything is null.

use
#Html.TextBoxFor(...
instead of
#Html.DisplayFor(....
That way the view will then pass them to the controller 'edit' HttpPost ActionResult after form submission.
The
#Html.DisplayFor(...
Is only used for outputting the model to the screen. It does not, however, allow them to be edited in this way (Hence use the TextBoxFor or EditorFor instead)
I'm not too sure if you want the 'exitDate' and exitTime to be manually edited or not, but if you do, then you will need to add them to your view, as well as including them in your Binding Property after adding them to your model.
If you do, then using something like:
(Guest guest)
instead of binding the data
Should include a binding for that.

Related

The ViewData item that has the key 'Position' is of type 'System.String' but must be of type 'IEnumerable<SelectListItem>' [duplicate]

This question already has answers here:
The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'
(6 answers)
Closed 6 years ago.
I am populating DropDownList from in-memory data and getting this error on POST.
The ViewData item that has the key 'Position' is of type 'System.String' but must be of type 'IEnumerable'.
Model:
public class StaffModel
{
public int id { get; set; }
public string Email { get; set; }
[DataType(DataType.Password)]
public string Password { get; set; }
[DataType(DataType.Password)]
public string PasswordConfirm { get; set; }
public string Emp_Name { get; set; }
public string Emp_Address { get; set; }
public string Phone { get; set; }
public string Position { get; set; }
public List<SelectListItem> Positions { set; get; }
}
Controller:
public ActionResult Register()
{
IEnumerable<SelectListItem> position = db.Positions.Select(p => new SelectListItem
{
Text = p.Position_Title,
Value = p.Position_ID.ToString()
});
ViewBag.Position = position;
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(StaffModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
Employee em = new Employee
{
Employee_Name = model.Emp_Name,
Address = model.Emp_Address,
Phone = model.Phone,
Position_ID = Convert.ToInt32(db.Positions.Where(p => p.Position_Title == model.Position).Select(p => p.Position_ID)),
};
db.Employees.Add(em);
db.SaveChanges();
return RedirectToAction("Index", "Employees");
}
}
return View(model);
}
enter code here
HTML/Razor:
<div class="form-group">
#Html.LabelFor(model => model.Position, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("Position",null, htmlAttributes: new { #class = "form-control" } )
#Html.ValidationMessageFor(model => model.Position, "", new { #class = "text-danger" })
</div>
</div>
Your binding on the drop down list doesn't look right.
You're model contains Positions which is the data for your drop down. You also have "Position" which I presume is a string that will be bound to the selected value in the drop down.
Change your view to
#Html.DropDownListFor(x=> x.Position, Model.Positions, new {#class = "form-control"}) )
Then on your post, it looks as if you are trying to get the value selected from the drop down by performing a linq query on the "Positions" list of the model which was used to populate your dropdown. You should now have the selected value in the "Position" property of your model.
So you should say
Position_ID = model.Position
I'd also use a model for your Register View.
Something like...
public class RegisterViewModel
{
public IEnumerable<SelectListItem> Positions { get; set; }
public string Position { get; set; }
}
Plus the additional fields you need.
The in your Register action method, populate the view model and return the view.
public ActionResult Register()
{
var regModel = new RegisterViewModel
{
Positions = db.Positions.Select(p => new SelectListItem
{
Text = p.Position_Title,
Value = p.Position_ID.ToString()
})
};
return View("Register",regModel);
}
You don't need to use ViewBag now.
Hope that helps
it work correctly. thank everybody help me:D
Model:
public class StaffModel
{
public string Position { get; set; }
public List<Position> Positions { set; get; }
public int selectID { get; set; }
}
Controller:
public ActionResult Register()
{
StaffModel st = new StaffModel();
st.Positions = db.Positions.ToList();
return View(st);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Register(StaffModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = UserManager.Create(user, model.Password);
if (result.Succeeded)
{
Employee em = new Employee
{
Employee_Name = model.Emp_Name,
Address = model.Emp_Address,
Phone = model.Phone,
Position_ID = model.selectID,
ID_User = user.Id
};
db.Employees.Add(em);
db.SaveChanges();
return RedirectToAction("Index", "Employees");
}
else
AddErrors(result);
}
ViewBag.Position = new SelectList(db.Positions, "Position_ID", "Position_Title");
return View(model);
}
HTML/Razor:
<div class="form-group">
#Html.LabelFor(model => model.Position, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model=>model.selectID,new SelectList(Model.Positions, "Position_ID", "Position_Title"), htmlAttributes: new { #class = "form-control" } )
#Html.ValidationMessageFor(model => model.Position, "", new { #class = "text-danger" })
</div>
</div>

Issue extending the base EDMX model and calling the functions in the data model

I am writing a solution using MVC with scaffolding. It uses Entity Framework v6 and is database first in design. The base data model (ServiceAccountFilter) is extended by the data model (FilterModel). There is some logic in the FilterModel but the properties are all inherited from the base model. It seems as though the controller insists on using the base model. When I change the return to use the FilterModel, I get an error that the view requires the base model and then the functions in the FilterModel are not visible in the views? Not sure how to handle this?
Base Model:
namespace FHN.ARX.AdminWeb
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
public partial class ServiceAccountFilter
{
[DisplayName("Filter ID")]
public virtual int FilterId { get; set; }
[DisplayName("Filter Name")]
public virtual string FilterName { get; set; }
[DisplayName("Service Account")]
public virtual string ServiceAccount { get; set; }
[DisplayName("Doc Type")]
public virtual string DocType { get; set; }
[DisplayName("Doc Type ID")]
public virtual Nullable<int> DocTypeId { get; set; }
[DisplayName("Doc Name ID")]
public virtual string DocNameId { get; set; }
[DisplayName("Last Modified By ID")]
public virtual string LastModifiedById { get; set; }
[DisplayName("Last Modified By")]
public virtual string LastModifiedByName { get; set; }
[DisplayName("Last Modified")]
public virtual Nullable<System.DateTime> LastModified { get; set; }
[DisplayName("Months To Return")]
public virtual Nullable<int> MonthsToReturn { get; set; }
}
}
FilterModel
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace FHN.ARX.AdminWeb.Models
{
public class FilterModel : ServiceAccountFilter
{
[DisplayName("Filter ID")]
public override int FilterId { get; set; }
[DisplayName("Filter Name")]
public override string FilterName { get; set; }
[DisplayName("Service Account")]
public override string ServiceAccount { get; set; }
[DisplayName("Doc Type")]
public override string DocType { get; set; }
[DisplayName("Doc Type ID")]
public override Nullable<int> DocTypeId { get; set; }
[DisplayName("Doc Name ID")]
public override string DocNameId { get; set; }
[DisplayName("Last Modified By ID")]
public override string LastModifiedById { get; set; }
[DisplayName("Last Modified By")]
public override string LastModifiedByName { get; set; }
[DisplayName("Last Modified")]
public override Nullable<System.DateTime> LastModified { get; set; }
[DisplayName("Months To Return")]
public override Nullable<int> MonthsToReturn { get; set; }
public bool Selected { get; set; }
public string Checkboxes { get; set; }
public IEnumerable<SelectListItem> DocTypesList(string id)
{
using (var db = new ARXEntities())
{
var docType = new List<SelectListItem>();
docType = (from t in db.vwMapDocNamesToSecurityUsers
where t.UserDN == id
orderby t.DocType
select new { t.DocType, t.DocTypeId }).Distinct().Select(x => new SelectListItem() { Text = x.DocType, Value = x.DocTypeId.ToString() }).OrderBy(x => x.Text).ToList();
return docType;
}
}
public IEnumerable<SelectListItem> DocNamesList()
{
using (var db = new ARXEntities())
{
IEnumerable<SelectListItem> docName = new List<SelectListItem>();
var loggedInUser = "C2693"; // HttpContext.Current.User.Identity.Name.Split('\\')[1];
docName = (from t in db.vwMapDocNamesToSecurityUsers
where t.UserDN == loggedInUser
select new { t.DocName, t.DocNameId, t.DocTypeId }).Distinct().Select(x => new SelectListItem()
{
Text = x.DocName,
Value = x.DocNameId.ToString(),
Group = new SelectListGroup() { Name = x.DocTypeId.ToString() }
}).Distinct().OrderBy(x => x.Text).ToList();
var docCount = docName.Count();
return docName;
}
}
public IEnumerable<SelectListItem> ServiceAccountList()
{
using (var db = new ARXEntities())
{
var sa = new List<SelectListItem>();
sa = (from t in db.vwMapDocNamesToSecurityUsers
where t.UserDN.StartsWith("sa_")
orderby t.UserDN
select new { t.UserDN }).Distinct().Select(x => new SelectListItem() { Text = x.UserDN, Value = x.UserDN }).OrderBy(x => x.Text).ToList();
return sa;
}
}
public IEnumerable<SelectListItem> DocNamesByDocTypeIdList()
{
using (var db = new ARXEntities())
{
IEnumerable<SelectListItem> docName = new List<SelectListItem>();
docName = (from t in db.vwMapDocNamesToSecurityUsers
select new { t.DocName, t.DocNameId, t.DocTypeId }).Distinct().Select(x => new SelectListItem()
{
Text = x.DocName,
Value = x.DocNameId.ToString(),
Group = new SelectListGroup() { Name = x.DocTypeId.ToString() }
}).Distinct().OrderBy(x => x.Text).ToList();
var docCount = docName.Count();
return docName;
}
}
public IEnumerable<SelectListItem> GetDocNamesForFilterId(int? id)
{
using (var db = new ARXEntities())
{
IEnumerable<SelectListItem> docName = new List<SelectListItem>();
docName = (from t in db.ServiceAccountFilters
where t.FilterId == id
select new { t.DocNameId, t.FilterId }).Distinct().Select(x => new SelectListItem()
{
Text = x.DocNameId,
Value = x.DocNameId.ToString(),
Group = new SelectListGroup() { Name = x.DocNameId.ToString() }
}).Distinct().OrderBy(x => x.Text).ToList();
return docName;
}
}
}
}
Controller Edit Action
public ActionResult Edit(int? id)
{
if (id == null)
{
var saf = new FilterModel();
return View(saf);
}
FilterModel serviceAccountFilter = (FilterModel)db.ServiceAccountFilters.Find(id); <----Tried casting here, but still didnt work.
if (serviceAccountFilter == null)
{
return HttpNotFound();
}
return View(serviceAccountFilter);
}
Edit View
#model FHN.ARX.AdminWeb.Models.FilterModel
#{
ViewBag.Title = "Edit A Filter";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="pageTitle">Filter Maintenance</div>
#using (Html.BeginForm(new { id = "filterForm" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.FilterId)
#Html.HiddenFor(model => model.LastModified)
#Html.HiddenFor(model => model.LastModifiedById)
#Html.HiddenFor(model => model.LastModifiedByName)
<div class="ddlGroups, btmMarg-15">
#Html.DropDownListFor(m => m.ServiceAccount, Model.ServiceAccountList(), "Select a Service Account")
</div>
<div class="ddlGroups, col-md-10, btmMarg-15">
#Html.LabelFor(model => model.ServiceAccount, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.ServiceAccount, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="ddlGroups, col-md-10, btmMarg-15">
#Html.LabelFor(model => model.DocTypeId, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.DocTypeId, new { htmlAttributes = new { #class = "form-control" } })
</div>
<p class="leftMarg-15 text-default" id="docNamesHdrText">Select the document names to be included in the filter.</p>
<div class="ckDocNames">
#foreach (var dn in Model.DocNamesByDocTypeIdList())
{
<div class="checkboxContainer">
<input class="ckBoxes" type="checkbox" name="DocNameId" value="#dn.Value" dtid="#dn.Group.Name" />#dn.Text<br />
</div>
}
</div>
<div class="form-group, col-md-10, btmMarg-15" id="monthsGroup">
#Html.LabelFor(model => model.MonthsToReturn, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.MonthsToReturn, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.MonthsToReturn, "", new { #class = "text-danger" })
</div>
<div class="form-group, col-md-10, btmMarg-15" id="filterNameGroup">
#Html.LabelFor(model => model.FilterName, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.FilterName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FilterName, "", new { #class = "text-danger" })
</div>
<br />
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" id="modSaveButton" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "ActiveFilters") |
#Html.ActionLink("Admin Home", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
this is an example of using a viewmodel on your case ... (may be it's not prefect but just a hint on your way)
namespace FHN.ARX.AdminWeb
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
public partial class ServiceAccountFilter
{
public int FilterId { get; set; }
public string FilterName { get; set; }
public string ServiceAccount { get; set; }
public string DocType { get; set; }
public Nullable<int> DocTypeId { get; set; }
public string DocNameId { get; set; }
public string LastModifiedById { get; set; }
public string LastModifiedByName { get; set; }
public Nullable<System.DateTime> LastModified { get; set; }
public Nullable<int> MonthsToReturn { get; set; }
}
}
no need for the filter model now and instead of that put all the logic in the controller under a heper region
#region Helpers
public IEnumerable<SelectListItem> DocTypesList(string id)
{
using (var db = new ARXEntities())
{
var docType = new List<SelectListItem>();
docType = (from t in db.vwMapDocNamesToSecurityUsers
where t.UserDN == id
orderby t.DocType
select new { t.DocType, t.DocTypeId }).Distinct().Select(x => new SelectListItem() { Text = x.DocType, Value = x.DocTypeId.ToString() }).OrderBy(x => x.Text).ToList();
return docType;
}
}
public IEnumerable<SelectListItem> DocNamesList()
{
using (var db = new ARXEntities())
{
IEnumerable<SelectListItem> docName = new List<SelectListItem>();
var loggedInUser = "C2693"; // HttpContext.Current.User.Identity.Name.Split('\\')[1];
docName = (from t in db.vwMapDocNamesToSecurityUsers
where t.UserDN == loggedInUser
select new { t.DocName, t.DocNameId, t.DocTypeId }).Distinct().Select(x => new SelectListItem()
{
Text = x.DocName,
Value = x.DocNameId.ToString(),
Group = new SelectListGroup() { Name = x.DocTypeId.ToString() }
}).Distinct().OrderBy(x => x.Text).ToList();
var docCount = docName.Count();
return docName;
}
}
public IEnumerable<SelectListItem> ServiceAccountList()
{
using (var db = new ARXEntities())
{
var sa = new List<SelectListItem>();
sa = (from t in db.vwMapDocNamesToSecurityUsers
where t.UserDN.StartsWith("sa_")
orderby t.UserDN
select new { t.UserDN }).Distinct().Select(x => new SelectListItem() { Text = x.UserDN, Value = x.UserDN }).OrderBy(x => x.Text).ToList();
return sa;
}
}
public IEnumerable<SelectListItem> DocNamesByDocTypeIdList()
{
using (var db = new ARXEntities())
{
IEnumerable<SelectListItem> docName = new List<SelectListItem>();
docName = (from t in db.vwMapDocNamesToSecurityUsers
select new { t.DocName, t.DocNameId, t.DocTypeId }).Distinct().Select(x => new SelectListItem()
{
Text = x.DocName,
Value = x.DocNameId.ToString(),
Group = new SelectListGroup() { Name = x.DocTypeId.ToString() }
}).Distinct().OrderBy(x => x.Text).ToList();
var docCount = docName.Count();
return docName;
}
}
public IEnumerable<SelectListItem> GetDocNamesForFilterId(int? id)
{
using (var db = new ARXEntities())
{
IEnumerable<SelectListItem> docName = new List<SelectListItem>();
docName = (from t in db.ServiceAccountFilters
where t.FilterId == id
select new { t.DocNameId, t.FilterId }).Distinct().Select(x => new SelectListItem()
{
Text = x.DocNameId,
Value = x.DocNameId.ToString(),
Group = new SelectListGroup() { Name = x.DocNameId.ToString() }
}).Distinct().OrderBy(x => x.Text).ToList();
return docName;
}
}
#endregion
in your controller Edit Action
public ActionResult Edit(int? id)
{
if (id == null)
{
var saf = new FilterModel();
return View(saf);
}
var serviceAccountFilter = db.ServiceAccountFilters.Find(id)
if (serviceAccountFilter == null)
{
return HttpNotFound();
}
var model = new FilterViewModel
{
FilterId = serviceAccountFilter.FilterId,
FilterName = serviceAccountFilter.FilterName,
ServiceAccount = serviceAccountFilter.ServiceAccount,
DocType = serviceAccountFilter.DocType,
DocTypeId = serviceAccountFilter.DocTypeId,
DocNameId = serviceAccountFilter.DocNameId,
LastModifiedById = serviceAccountFilter.LastModifiedById,
LastModifiedByName = serviceAccountFilter.LastModifiedByName,
LastModified = serviceAccountFilter.LastModified,
MonthsToReturn = serviceAccountFilter.MonthsToReturn,
ServiceAccountList = ServiceAccountList(),
DocNamesByDocTypeIdList = DocNamesByDocTypeIdList()
};
return View(model);
}
and here is a ViewModel lets say it's name will be FilterViewModel
public class FilterModel
{
[DisplayName("Filter ID")]
public int FilterId { get; set; }
[DisplayName("Filter Name")]
public string FilterName { get; set; }
[DisplayName("Service Account")]
public string ServiceAccount { get; set; }
[DisplayName("Doc Type")]
public string DocType { get; set; }
[DisplayName("Doc Type ID")]
public Nullable<int> DocTypeId { get; set; }
[DisplayName("Doc Name ID")]
public string DocNameId { get; set; }
[DisplayName("Last Modified By ID")]
public string LastModifiedById { get; set; }
[DisplayName("Last Modified By")]
public string LastModifiedByName { get; set; }
[DisplayName("Last Modified")]
public Nullable<System.DateTime> LastModified { get; set; }
[DisplayName("Months To Return")]
public Nullable<int> MonthsToReturn { get; set; }
public IEnumerable<SelectListItem> ServiceAccountList { get; set; }
public IEnumerable<SelectListItem> DocNamesByDocTypeIdList { get; set; }
}
and then your Edit View will be
#model FilterViewModel // check the name space
#{
ViewBag.Title = "Edit A Filter";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="pageTitle">Filter Maintenance</div>
#using (Html.BeginForm(new { id = "filterForm" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.FilterId)
#Html.HiddenFor(model => model.LastModified)
#Html.HiddenFor(model => model.LastModifiedById)
#Html.HiddenFor(model => model.LastModifiedByName)
<div class="ddlGroups, btmMarg-15">
#Html.DropDownListFor(m => m.ServiceAccount, Model.ServiceAccountList(), "Select a Service Account")
</div>
<div class="ddlGroups, col-md-10, btmMarg-15">
#Html.LabelFor(model => model.ServiceAccount, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.ServiceAccount, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="ddlGroups, col-md-10, btmMarg-15">
#Html.LabelFor(model => model.DocTypeId, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.DocTypeId, new { htmlAttributes = new { #class = "form-control" } })
</div>
<p class="leftMarg-15 text-default" id="docNamesHdrText">Select the document names to be included in the filter.</p>
<div class="ckDocNames">
#foreach (var dn in Model.DocNamesByDocTypeIdList())
{
<div class="checkboxContainer">
<input class="ckBoxes" type="checkbox" name="DocNameId" value="#dn.Value" dtid="#dn.Group.Name" />#dn.Text<br />
</div>
}
</div>
<div class="form-group, col-md-10, btmMarg-15" id="monthsGroup">
#Html.LabelFor(model => model.MonthsToReturn, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.MonthsToReturn, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.MonthsToReturn, "", new { #class = "text-danger" })
</div>
<div class="form-group, col-md-10, btmMarg-15" id="filterNameGroup">
#Html.LabelFor(model => model.FilterName, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.FilterName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FilterName, "", new { #class = "text-danger" })
</div>
<br />
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" id="modSaveButton" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "ActiveFilters") |
#Html.ActionLink("Admin Home", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}

ASP.NET MVC5 - Validate against other table

Using VS2013 and building my first MVC app with EF6 (database first). I have a jobs table and a related items table (there can be millions of records per job). I need to give the user a way to export a subset of items (e.g. item 1,000 - 10,000).
So my controller contains a get method that opens a new view where they can enter the start and end values.
I want to default these to the min and max values from the items table and then I need to validate that the two numbers entered exist in the items table.
Here's my view:
#model PSAMVC.Models.Job
#{
ViewBag.Title = "ExportToLake";
}
<h2>ExportToLake</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Job</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.ID)
<div class="form-group">
#Html.LabelFor(model => model.JobNo, "JobNo", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DisplayFor(model => model.JobNo, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.VersionRef, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DisplayFor(model => model.VersionRef, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PSAJobRef, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DisplayFor(model => model.PSAJobRef, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
#Html.Label("Start Seq No", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBox("StartSeqNo")
</div>
</div>
<div class="form-group">
#Html.Label("End Seq No", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBox("EndSeqNo")
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Export" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
How/where would I enter the code to validate the two numbers against the items table?
I would think that doing in the view is the best place as the user would get immediate feedback and I can code the controller method knowing it will always be passed valid values.
I could add a view to Db that contains the job no and min and max item no, but it seems like a bit of a hack.
TIA
Mark
Update: here's my Jobs model:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace PSAMVC.Models
{
using System;
using System.Collections.Generic;
public partial class Job
{
public Job()
{
this.Items = new HashSet<Item>();
this.Reprints = new HashSet<Reprint>();
this.Scans = new HashSet<Scan>();
this.LabelTypes = new HashSet<LabelType>();
}
public int ID { get; set; }
public string JobNo { get; set; }
public string VersionRef { get; set; }
public string PSAJobRef { get; set; }
public int TotalCopies { get; set; }
public int CopiesPerBundle { get; set; }
public int CopiesPerCarton { get; set; }
public int CopiesPerMasterCarton { get; set; }
public Nullable<int> CopiesPerPallet { get; set; }
public int CardType { get; set; }
public string CardTitle { get; set; }
public string CardMMYY { get; set; }
public string StartSerialNo { get; set; }
public int StartBundleNo { get; set; }
public int StartCartonNo { get; set; }
public Nullable<int> StartMasterCartonNo { get; set; }
public Nullable<int> StartPalletNo { get; set; }
public string ProductUPC { get; set; }
public string PackagingUPC { get; set; }
public bool PreProcessed { get; set; }
public bool Completed { get; set; }
public Nullable<int> FormatFileID { get; set; }
public bool UseDummyBarcode { get; set; }
public bool Samples { get; set; }
public string PartNo { get; set; }
public string ProductEAN { get; set; }
public string PONo { get; set; }
public string ImportedFileList { get; set; }
public bool ExportedToLake { get; set; }
public Nullable<int> TotalPalletsOverride { get; set; }
public virtual CardType CardType1 { get; set; }
public virtual FormatFile FormatFile { get; set; }
public virtual ICollection<Item> Items { get; set; }
public virtual SG360JobNos SG360JobNos { get; set; }
public virtual ICollection<Reprint> Reprints { get; set; }
public virtual ICollection<Scan> Scans { get; set; }
public virtual ICollection<LabelType> LabelTypes { get; set; }
}
}
and here's my jobs controller
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using PSAMVC.Models;
using System.Data.SqlClient;
using System.Configuration;
namespace PSAMVC.Controllers
{
public class JobsController : Controller
{
private PSAMVCEntities db = new PSAMVCEntities();
// GET: Jobs
public ActionResult Index()
{
var jobs = db.Jobs.Include(j => j.CardType1).Include(j => j.FormatFile).Include(j => j.SG360JobNos);
return View(jobs.ToList());
}
// GET: Jobs/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Job job = db.Jobs.Find(id);
if (job == null)
{
return HttpNotFound();
}
return View(job);
}
// GET: Jobs/Create
public ActionResult Create()
{
ViewBag.CardType = new SelectList(db.CardTypes, "ID", "Description");
ViewBag.FormatFileID = new SelectList(db.FormatFiles, "ID", "Name");
ViewBag.JobNo = new SelectList(db.SG360JobNos, "JobNo", "JobNo");
return View();
}
// GET: CreateBundlesAndCartons
public ActionResult CreateBandC(Int32 id)
{
string ReturnMessage;
ReturnMessage = "";
using (SqlConnection connection = new SqlConnection())
{
//string connectionStringName = this.DataWorkspace.CooperData.Details.Name;
connection.ConnectionString =
ConfigurationManager.ConnectionStrings["PSAContext"].ConnectionString;
string procedure = "PSA.dbo.CreateBundlesAndCartons";
using (SqlCommand command = new SqlCommand(procedure, connection))
{
command.CommandType = CommandType.StoredProcedure;
command.CommandTimeout = 300;
command.Parameters.Add(
new SqlParameter("#JobID", id));
SqlParameter ErrorString = new SqlParameter("#ErrorString", ReturnMessage);
ErrorString.Direction = ParameterDirection.Output;
ErrorString.Size = 4000;
command.Parameters.Add(ErrorString);
connection.Open();
command.ExecuteNonQuery();
// Save Outout Param
ReturnMessage = ErrorString.Value.ToString();
#ViewBag.Results = ReturnMessage;
}
}
//return Content("You requested the to create bundles and cartons for job ID " + id.ToString() + "<br />Result: " + ReturnMessage + "<br /> Return to Jobs");
return PartialView("_SPResults");
}
// GET: Jobs/ExportToLake/5
public ActionResult ExportToLake(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Job job = db.Jobs.Find(id);
if (job == null)
{
return HttpNotFound();
}
ViewBag.JobNo = new SelectList(db.SG360JobNos, "JobNo", "JobNo", job.JobNo);
return View(job);
}
// GET: ExportToLake1
public ActionResult ExportToLake1(Int32 id, Int64 StartSeqNo, Int64 EndSeqNo, Boolean ReverseOrder, String FileNameSuffix)
{
string ReturnMessage;
ReturnMessage = "";
using (SqlConnection connection = new SqlConnection())
{
//string connectionStringName = this.DataWorkspace.CooperData.Details.Name;
connection.ConnectionString =
ConfigurationManager.ConnectionStrings["PSAContext"].ConnectionString;
string procedure = "PSA.dbo.ExportToLakeBulk";
using (SqlCommand command = new SqlCommand(procedure, connection))
{
command.CommandType = CommandType.StoredProcedure;
command.CommandTimeout = 1200;
command.Parameters.Add(
new SqlParameter("#JobID", id));
command.Parameters.Add(
new SqlParameter("#ReverseOrder", ReverseOrder));
command.Parameters.Add(
new SqlParameter("#StartSeqNo", StartSeqNo));
command.Parameters.Add(
new SqlParameter("#EndSeqNo", EndSeqNo));
command.Parameters.Add(
new SqlParameter("#Suffix", FileNameSuffix));
SqlParameter ErrorString = new SqlParameter("#ErrorString", ReturnMessage);
ErrorString.Direction = ParameterDirection.Output;
ErrorString.Size = 4000;
command.Parameters.Add(ErrorString);
connection.Open();
command.ExecuteNonQuery();
// Save Outout Param
ReturnMessage = ErrorString.Value.ToString();
#ViewBag.Results = ReturnMessage;
}
}
//return Content("You requested the to create bundles and cartons for job ID " + id.ToString() + "<br />Result: " + ReturnMessage + "<br /> Return to Jobs");
return PartialView("_SPResults");
}
// POST: Jobs/ExportToLake
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ExportToLake2([Bind(Include = "ID,StartSeqNo,EndSeqNo,ReverseOrder")] Job job)
{
if (ModelState.IsValid)
{
//db.Jobs.Add(job);
//db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CardType = new SelectList(db.CardTypes, "ID", "Description", job.CardType);
ViewBag.FormatFileID = new SelectList(db.FormatFiles, "ID", "Name", job.FormatFileID);
ViewBag.JobNo = new SelectList(db.SG360JobNos, "JobNo", "JobNo", job.JobNo);
return View(job);
}
// POST: Jobs/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,JobNo,VersionRef,PSAJobRef,TotalCopies,CopiesPerBundle,CopiesPerCarton,CopiesPerMasterCarton,CopiesPerPallet,CardType,CardTitle,CardMMYY,StartSerialNo,StartBundleNo,StartCartonNo,StartMasterCartonNo,StartPalletNo,ProductUPC,PackagingUPC,PreProcessed,Completed,FormatFileID,UseDummyBarcode,Samples,PartNo,ProductEAN,PONo,ImportedFileList,ExportedToLake,TotalPalletsOverride")] Job job)
{
if (ModelState.IsValid)
{
db.Jobs.Add(job);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CardType = new SelectList(db.CardTypes, "ID", "Description", job.CardType);
ViewBag.FormatFileID = new SelectList(db.FormatFiles, "ID", "Name", job.FormatFileID);
ViewBag.JobNo = new SelectList(db.SG360JobNos, "JobNo", "JobNo", job.JobNo);
return View(job);
}
// GET: Jobs/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Job job = db.Jobs.Find(id);
if (job == null)
{
return HttpNotFound();
}
ViewBag.CardType = new SelectList(db.CardTypes, "ID", "Description", job.CardType);
ViewBag.FormatFileID = new SelectList(db.FormatFiles, "ID", "Name", job.FormatFileID);
ViewBag.JobNo = new SelectList(db.SG360JobNos, "JobNo", "JobNo", job.JobNo);
return View(job);
}
// POST: Jobs/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ID,JobNo,VersionRef,PSAJobRef,TotalCopies,CopiesPerBundle,CopiesPerCarton,CopiesPerMasterCarton,CopiesPerPallet,CardType,CardTitle,CardMMYY,StartSerialNo,StartBundleNo,StartCartonNo,StartMasterCartonNo,StartPalletNo,ProductUPC,PackagingUPC,PreProcessed,Completed,FormatFileID,UseDummyBarcode,Samples,PartNo,ProductEAN,PONo,ImportedFileList,ExportedToLake,TotalPalletsOverride")] Job job)
{
if (ModelState.IsValid)
{
db.Entry(job).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CardType = new SelectList(db.CardTypes, "ID", "Description", job.CardType);
ViewBag.FormatFileID = new SelectList(db.FormatFiles, "ID", "Name", job.FormatFileID);
ViewBag.JobNo = new SelectList(db.SG360JobNos, "JobNo", "JobNo", job.JobNo);
return View(job);
}
// GET: Jobs/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Job job = db.Jobs.Find(id);
if (job == null)
{
return HttpNotFound();
}
return View(job);
}
// POST: Jobs/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Job job = db.Jobs.Find(id);
db.Jobs.Remove(job);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
Firstly the server side code should not assume that the values being passed are valid. Always validate the values and handle errors correctly. Client side validation can be bypassed.
In terms of providing instant feedback, one approach is to have an action on a controller that accepts the value to validate as a parameter and returns json containing whether the value was valid and if not the error.
This action can then be called on the input fields blur event or change even providing close to real time feedback on whether the values are valid.
Another approach is to have the valid values determined during the page rendering process and embedded into the client side validation framework if you have one (or use custom JS).
Client Code
function performValidate(data, url) {
var result = $.ajax({
type: "POST",
url: url,
data: data,
success: function (data) {
if (!data.success) {
//HandleIncorrectValue
}
//HandleCorrectValue
},
error: function (data) {
//HandleError
}
});
Controller Code
[HttpPost]
public ActionResult Validate(int value)
{
var response = ValidateValue(value);
return Json(new { success = response.Success, message = response.Message });
}

POST Action Losing Values

I populate my view with model values for UseCaseId and ExtensionPoint - debugging through this seems to work fine.
However, when I add a new bit of information to the ExtensionTitle field on my view and then POST, only the value for ExtensionTitle is retained and the values for UseCaseId and ExtensionPoint are lost. This means that if (ModelState.IsValid) returns false and therefore I can't save the new record to the database.
Can anyone tell me why these values are getting lost when I POST?
VIEWMODEL
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web;
namespace JustSpecIt.ViewModels
{
public class AddExtensionStepViewModel
{
public int UseCaseId { get; set; }
[DisplayName ("Extends Step #")]
public int ExtensionPoint { get; set; }
[DisplayName ("Extends Step Description")]
public string StepTitle { get; set; }
[DisplayName("Extension Name")]
public string ExtensionTitle { get; set; }
}
}
MODEL
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace JustSpecIt.Models
{
public class Extension
{
public int ID { get; set; }
public int UseCaseID { get; set; }
public string Title { get; set; }
public int ExtensionPoint { get; set; }
}
}
CONTROLLER
// GET: Extensions/Create
public ActionResult Create(int id)
{
ViewBag.UseCaseId = id;
ViewBag.StepTitle = db.Steps.Find(id).Content;
//Create an populate the ViewModel
AddExtensionStepViewModel model = new AddExtensionStepViewModel()
{
ExtensionPoint = id,
UseCaseId = db.Steps.Find(id).UseCaseID,
};
return View();
}
// POST: Extensions/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "UseCaseId,ExtensionTitle,ExtensionPoint")] AddExtensionStepViewModel model)
{
if (ModelState.IsValid)
{
Extension e = new Extension ();
e.ExtensionPoint = model.ExtensionPoint;
e.UseCaseID = model.UseCaseId;
e.Title = model.ExtensionTitle;
db.Extensions.Add(e);
db.SaveChanges();
return RedirectToAction("ChooseExtensionStep", new { id = model.UseCaseId });
}
return View(model);
}
VIEW
#model JustSpecIt.ViewModels.AddExtensionStepViewModel
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Add Extension Step</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.UseCaseId)
#Html.HiddenFor(model => model.ExtensionPoint)
<div class="form-horizontal">
<h4>Extension</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.ExtensionTitle, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-10">
#Html.EditorFor(model => model.ExtensionTitle, new { htmlAttributes = new { #class = "form-control form-control-no-max-width" } })
#Html.ValidationMessageFor(model => model.ExtensionTitle, "", new { #class = "text-danger" })
</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>
}
You have not passed the model to the view in your GET method (so the values of UseCaseID and Title are 0 (the defaults for int)
public ActionResult Create(int id)
{
ViewBag.UseCaseId = id;
ViewBag.StepTitle = db.Steps.Find(id).Content;
AddExtensionStepViewModel model = new AddExtensionStepViewModel()
{
ExtensionPoint = id,
UseCaseId = db.Steps.Find(id).UseCaseID,
};
return View(model); // change this
}

Passing Model Object Data from View, to Controller, to Model?

I'm brand new to ASP.net MVC (About a week in), so there is still quite a bit of confusion...
How do I go about passing the current views model into the controller so I can get at the model data?
View
#model KineticBomardment.Models.Blog.BlogPost
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm())
{
#Html.ValidationSummary(false)
<fieldset class="block">
<div class="input">
#Html.LabelFor(x => x.Title)
#Html.EditorFor(x => x.Title)
</div>
<div class="input">
#Html.LabelFor(x => x.ShortDescription)
#Html.EditorFor(x => x.ShortDescription)
</div>
<div class="button">
#Html.ActionLink("Submit", "CreateNewBlogEntry", "Admin" );
</div>
</fieldset>
}
I then have a controller of
public ActionResult CreateNewBlogEntry(Models.Blog.BlogPost currentBlogModel)
{
if (ModelState.IsValid)
{
currentBlogModel.CreatePost();
return Content("Created!");
}
return View();
}
And a model of
public class BlogPost
{
public int Id { get; set; }
[Required]
[Display(Name="Title of Blog Post")]
public string Title { get; set; }
public DateTime DateCreated { get; set; }
[Required]
[Display(Name = "Short Description")]
public string ShortDescription { get; set; }
public string LongDescription { get; set; }
public int HeaderImage { get; set; }
public ICollection<BlogPost> GetAllPosts()
{
ICollection<BlogPost> posts = new List<BlogPost>();
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["KineticBombardment"].ToString()))
{
using (SqlCommand cmd = new SqlCommand("select title, datecreated, shortdescription from blogentries where id > 0", connection))
{
cmd.Parameters.Clear();
connection.Open();
cmd.ExecuteNonQuery();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while(reader.Read())
{
this.ShortDescription = reader["shortdescription"].ToString();
this.Title = reader["title"].ToString();
this.DateCreated = Convert.ToDateTime(reader["datecreated"].ToString());
posts.Add(this);
}
}
return posts;
}
}
}
public void CreatePost()
{
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["KineticBombardment"].ToString()))
{
using (SqlCommand cmd = new SqlCommand("insert into blogentries (shortdescription, datecreated, blogtype, title) values (#shortdescription, #datecreated, #blogtype, #title)", connection))
{
cmd.Parameters.Clear();
connection.Open();
cmd.Parameters.Add("#shortdescription", SqlDbType.VarChar, 500).Value = this.ShortDescription;
cmd.Parameters.Add("#datecreated", SqlDbType.DateTime).Value = DateTime.Now;
cmd.Parameters.Add("#blogtype", SqlDbType.Int).Value = 1;
cmd.Parameters.Add("#title", SqlDbType.VarChar, 255).Value = this.Title;
cmd.ExecuteNonQuery();
}
}
}
}
Change:
<div class="button">
#Html.ActionLink("Submit", "CreateNewBlogEntry", "Admin" );
</div>
To:
<input type="submit" class="button" />
and
public ActionResult CreateNewBlogEntry(Models.Blog.BlogPost currentBlogModel)
{
if (ModelState.IsValid)
{
currentBlogModel.CreatePost();
return Content("Created!");
}
return View();
}
to
public ActionResult CreateNewBlogEntry()
{
return View();
}
[HttpPost]
public ActionResult CreateNewBlogEntry(Models.Blog.BlogPost model)
{
if (ModelState.IsValid)
{
currentBlogModel.CreatePost();
return Content("Created!");
}
return View();
}
I've made some assumptions, but that should work

Resources