When I load this form
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Category Description</legend>
#Html.HiddenFor(model => Model.ID)
#Html.HiddenFor(model => Model.CategoryID)
#Html.DisplayFor(model => Model.Language)<br />
<div class="editor-field">
#Html.TextAreaFor(model => model.Text, new {} )
#Html.ValidationMessageFor(model => model.Text)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
The fields have the following values:
But after submitting the form, in the POST Method, the ID gets overwritten by the other Guid and the Language Field is null.
The Data Model looks like this:
public partial class Category_Description
{
public System.Guid ID { get; set; }
public System.Guid CategoryID { get; set; }
public string Language { get; set; }
public string Text { get; set; }
public virtual Category Category { get; set; }
}
What did I do wrong?
EDIT:
On Request the Post-Method:
[HttpPost]
public ActionResult CategoryDescription_Edit(Category_Description model)
{
if (ModelState.IsValid)
{
var result = dataService.SaveChanges(model);
if (result)
return RedirectToAction("Index");
}
return View(model);
}
And just in case the dataService.SaveChanges as well:
public bool SaveChanges(object model)
{
Portal_Context.Entry(model).State = EntityState.Modified;
return Portal_Context.SaveChanges() > 0 ? true : false;
}
The hint of #DanielJ.G. set me into the right direction.
The problem was the name of the parameter I used for the
#Html.ActionLink( ...., new {id = Model.CategoryID}, .....)
and the corresponding
public ActionResult Category_Delete(Guid id)
As soon as I renamed "id" to "category_id", the ID did not get overwritten anymore.
Related
I am using MVC Entity framework i have generated code i have fields Isactive this fields have values true or false . code looks like
controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="ClientId,ClientName,PrimaryContactName,EmailId,PrimaryContact,IsActive,ModifiedBy,ParentCompany")] TP_InternalClients tP_InternalClients)
{
if (ModelState.IsValid)
{
db.Entry(tP_InternalClients).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(tP_InternalClients);
}
model:
public class InternalClients
{
public int ClientId { get; set; }
public string ClientName { get; set; }
public string PrimaryContactName { get; set; }
public string EmailID { get; set; }
public string PrimaryContact { get; set; }
public bool IsActive { get; set; }
public string ModifiedBy { get; set; }
public int ParentCompany { get; set; }
}
View:
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.IsActive)
#Html.ValidationMessageFor(model => model.IsActive, "", new { #class = "text-danger" })
</div>
</div>
after run the code Isactive drop down showing true or false i want hidden field that time send value default true only to database . how i can hidden and send value default ? i doing i am getting error
In your form , simply replace
<div class="checkbox">
#Html.EditorFor(model => model.IsActive)
#Html.ValidationMessageFor(model => model.IsActive, "", new { #class = "text-danger" })
</div>
with
<input type="hidden" name="IsActive" value="true" />
Or you can use the Html helper method
#Html.HiddenFor(s=>s.IsActive)
Now make sure you set the default value to whatever you want in the GET action.
But, If you want a default value to be saved, Do it in your HttpPost action, No need to keep the Hidden field in the form (Users can update the hidden field value using browser dev tools)
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="ClientId,ClientName,PrimaryContactName,EmailId,
PrimaryContact,ModifiedBy,ParentCompany")] TP_InternalClients model)
{
if (ModelState.IsValid)
{
model.IsAcive = true ;
db.Entry(model).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(tP_InternalClients);
}
Remember, the best way to prevent overposting is to use a view model with only those properties needed for the view.
This is my Controller code.
public ActionResult Create()
{
ViewBag.grp_id = new SelectList(db.tm_grp_group, "grp_id", "grp_name");
ViewBag.perm_id = new SelectList(db.tm_perm_level, "perm_id", "perm_levelname");
return View();
}
Below is my view code.
#model Permission.ts_grp_perm_mapping
....
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>ts_grp_perm_mapping</legend>
<div class="editor-label">
#Html.LabelFor(model => model.grp_permid)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.grp_permid)
#Html.ValidationMessageFor(model => model.grp_permid)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.grp_id, "tm_grp_group")
</div>
<div class="editor-field">
#Html.DropDownList("grp_id", String.Empty)
#Html.ValidationMessageFor(model => model.grp_id)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.perm_id, "tm_perm_level")
</div>
<div class="editor-field">
#Html.DropDownList("perm_id", String.Empty)
#Html.ValidationMessageFor(model => model.perm_id)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
In controller ViewBag.perm_id contains some values (this is foreign key). In view perm.id displays in the form of dropdownbox but I want it in the form of checkboxlist. How can I achieve this?
This is the viewmodel I created.
public class AssignUserViewModel
{
public tm_perm_level[] perms { get; set; }
public int grp_id { get; set; }
}
Now in controller how can i send values to view? This is my tm_perm_level model
public partial class tm_perm_level
{
public tm_perm_level()
{
this.ts_grp_perm_mapping = new HashSet<ts_grp_perm_mapping>();
}
public int perm_id { get; set; }
public string perm_levelname { get; set; }
public string perm_description { get; set; }
public bool perm_status { get; set; }
public virtual ICollection<ts_grp_perm_mapping> ts_grp_perm_mapping { get; set; }
}
This is ts_grp_perm_mapping model
public partial class ts_grp_perm_mapping
{
public ts_grp_perm_mapping()
{
this.ts_perm_levelmapping = new HashSet<ts_perm_levelmapping>();
}
public int grp_permid { get; set; }
public int grp_id { get; set; }
public int perm_id { get; set; }
public List<tm_perm_level> permissions { get; set; }
public virtual tm_grp_group tm_grp_group { get; set; }
public virtual tm_perm_level tm_perm_level { get; set; }
public virtual ICollection<ts_perm_levelmapping> ts_perm_levelmapping { get; set; }
}
Especially when editing, always start with view models to represent what you want to display (refer What is ViewModel in MVC?)
public class PermissionVM
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
public class GroupPermissionVM
{
public int GroupID { get; set; }
public IEnumerable<SelectListItem> GroupList { get; set; }
public IEnumerable<PermissionVM> Permissions { get; set; }
}
Then create an EditorTemplate for PermissionVM. In the /Views/Shared/EditorTemplates/PermissionVM.cshtml folder
#model PermissionVM
<div>
#Html.HiddenFor(m => m.ID)
#Html.HiddenFor(m => m.Name)
#Html.CheckBoxFor(m => m.IsSelected)
#Html.LabelFor(m => m.IsSelected, Model.Name)
</div>
and the main view will be
#model GroupPermissionVM
....
#using (Html.BeginForm())
{
// dropdownlist
#Html.LabelFor(m => m.GroupID)
#Html.DropDownListFor(m => m.GroupID, Model.GroupList, "Please select")
#Html.ValidationMessageFor(m => m.GroupID)
// checkboxlist
#Html.EditorFor(m => m.Permissions)
<input type="submit" value="Create" />
}
The controller methods would then be
public ActionResult Create()
{
var groups = db.tm_grp_group;
var permissions = db.tm_perm_level;
GroupPermissionVM model = new GroupPermissionVM
{
GroupList = new SelectList(groups, "grp_id", "grp_name"),
Permissions = permissions.Select(p => new PermissionVM
{
ID = p.perm_id,
Name = p.perm_levelname
}
};
return View(model);
}
[HttpPost]
public ActionResult Create(GroupPermissionVM model)
{
if (!ModelState.IsValid)
{
var groups = db.tm_grp_group;
model.GroupList = new SelectList(groups, "grp_id", "grp_name");
return View(model);
}
// map the view model to a new instance of your data model(s)
// note: to get the ID's of the selected permissions -
// var selectedPermissions = model.Permissions.Where(p => p.IsSelected).Select(p => p.ID);
// save and redirect
}
Side note: I strongly recommend you follow normal naming conventions
Edit
Based on OP's comment for an option using radio buttons to select only one item, the revised code would be
public class PermissionVM
{
public int ID { get; set; }
public string Name { get; set; }
}
public class GroupPermissionVM
{
public int GroupID { get; set; }
public int PermissionID { get; set; }
public IEnumerable<SelectListItem> GroupList { get; set; }
public IEnumerable<PermissionVM> Permissions { get; set; }
}
and the view would be (no separate EditorTemplate required)
#model GroupPermissionVM
....
#using (Html.BeginForm())
{
// dropdownlist as above
// radio buttons
foreach (var permission in Model.Permissions)
{
<label>
#Html.RadioButtonForm(m => m.PermissionID, permission.ID)
<span>#permission.Name</span>
</label>
}
<input type="submit" value="Create" />
}
and in the POST method, the value of model.PermissionID will contain the ID of the selected Permission.
I am trying to bind a dropdown list from database in mvc3.
I have two tables.
tblEmp:
EmpID (pk),
EName,
Age,
Address,
EmailID,
DeptID (fk).
tblDept
DeptID (pk),
DeptName,
DeptHead.
I am trying to bind create an Employee application with the basic details of an employee
Name, Age, Address, EmailID, and Dept Name. I am trying to bind the Dept Name dropdownlist from the other table.
This is my Model:
namespace MvcEmployeeApplication.Models
{
public class UandPcompare
{
public int EmpID { get; set; }
public string EName { get; set; }
public int Age { get; set; }
public string Address { get; set; }
public string EmailID { get; set; }
public int DeptID { get; set; }
public string DeptName { get; set; }
public string DeptHead { get; set; }
public IList<SelectListItem> Drp_DeptNames { get; set; }
}
}
This is Controller:
[HttpGet]
public ActionResult Create()
{
FillDeptName();
return View();
}
[HttpPost]
public ActionResult Create(tblEmployee tblEmp)
{
test.Entry(tblEmp).State = System.Data.EntityState.Added;
test.SaveChanges();
return RedirectToAction("Index");
}
public ActionResult FillDeptName()
{
UandPcompare filldeptNme = new UandPcompare();
filldeptNme.Drp_DeptNames = (from DptName in test.tblDepts
select new SelectListItem()
{
Text = DptName.DeptName,
Value = SqlFunctions.StringConvert((double)DptName.DeptID)
}).ToList<SelectListItem>();
return View("Create");
}
This is MyView:
#model MvcEmployeeApplication.Models.UandPcompare
#{
ViewBag.title = "Edit";
}
<h2> Create </h2>
#using (Html.BeginForm())
{
<fieldset>
<legend> Create </legend>
<div>
Employee ID: #Html.DisplayFor(model => model.EmpID)
</div>
<div>
Employee Name: #Html.EditorFor(model => model.EName)
</div>
<div>
Email-ID: #Html.EditorFor(model => model.EmailID)
</div>
<div>
Address: #Html.EditorFor(model => model.Address)
</div>
<div>
Dept Name: #Html.DropDownList("DeptName", Model.Drp_DeptNames, "Select")
</div>
<p>
<input type="submit" value="Create" />
</p>
<div>
#Html.ActionLink("Back to Index", "Index");
</div>
Not able to get what error are you getting.
You are not passing any model to your view.
public ActionResult FillDeptName()
{
UandPcompare filldeptNme = new UandPcompare();
filldeptNme.Drp_DeptNames = (from DptName in test.tblDepts
select new SelectListItem()
{
Text = DptName.DeptName,
Value = SqlFunctions.StringConvert((double)DptName.DeptID)
}).ToList<SelectListItem>();
return View("Create",filldeptNme);//pass model to view here
}
I'm trying to create a controller to upload photos in my MVC4 application. But I keep getting this error. The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or a non-white space character among the padding characters.
PhotosController.cs
public class PhotoController : Controller
{
public ActionResult Index()
{
using (var ctx = new BlogContext())
{
return View(ctx.Photos.AsEnumerable());
}
}
public ActionResult Upload()
{
return View(new Photo());
}
[HttpPost]
public ActionResult Upload(PhotoViewModel model)
{
var photo = Mapper.Map<PhotoViewModel, Photo>(model);
if (ModelState.IsValid)
{
PhotoRepository.Save(photo);
return RedirectToAction("Index");
}
return View(photo);
}
}
Photo.cs
public class Photo
{
public int Id { get; set; }
public Byte[] File { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string AlternateText { get; set; }
}
PhotoViewModel.cs
public class PhotoViewModel
{
public int Id { get; set; }
public HttpPostedFileBase File { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string AlternateText { get; set; }
}
/Photos/Upload.cshtml
#model Rubish.Models.Photo
#{
ViewBag.Title = "Upload";
}
<h2>Upload</h2>
#using (Html.BeginForm("Upload","Photo",FormMethod.Post,new {enctype="multipart/form-data"})) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Photo</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Description)
#Html.ValidationMessageFor(model => model.Description)
</div>
<div class="editor-label">
<label for="file">FileName:</label>
</div>
<div class="editor-field">
<input name="File" id="File" type="file"/>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#Scripts.Render("~/bundles/jqueryval")
PhotoRepository
public class PhotoRepository
{
private static BlogContext _ctx;
public PhotoRepository()
{
_ctx = new BlogContext();
}
public static void Save(Photo p)
{
_ctx.Photos.Add(p);
_ctx.SaveChanges();
}
}
The problem is that you have a property in your view model called File which is of type byte[] and you are also using an action parameter called file of type HttpPostedFileBase. The problem is that when the model binder encounters a property on your model of type byte[] it attempts to bind its value from the request value using base64. Except that inside the request you have a multipart/form-data encoded value of the uploaded file and you get an exception.
The correct way to fix this is to use view models instead of passing your domain models to the views:
public class PhotoViewModel
{
public HttpPostedFileBase File { get; set; }
... other properties
}
and the controller action will now become:
[HttpPost]
public ActionResult Upload(PhotoViewModel model)
{
if (ModelState.IsValid)
{
// map the domain model from the view model that the action
// now takes as parameter
// I would recommend you AutoMapper for that purpose
Photo photo = ...
// Pass the domain model to a DAL layer for processing
Repository.Save(photo);
return RedirectToAction("Index");
}
return View(photo);
}
The poor way and totally not recommended by me is to rename your file input to trick the model binder:
<input name="PhotoFile" id="File" type="file"/>
and your controller action:
[HttpPost]
public ActionResult Upload(Photo photo, HttpPostedFileBase photoFile)
{
...
}
I am still struggling with learning ASP.NET MVC. All my form entries are required so I would like to do validation on them. For brevity I have paired my model down to Description (textbox) and Paradigm (dropdown). I am including Entry.cs, Paradigm.cs and EntryViewModel.cs Model classes and the Display.cshtml View.
[Bind(Exclude = "EntryId")]
public class Entry
{
[ScaffoldColumn(false)]
public int EntryId { get; set; }
[Required(ErrorMessage = "You must include a description.")]
public string Description { get; set; }
[Display(Name = "Type")]
[Required(ErrorMessage = "You must select a type.")]
public int ParadigmId { get; set; }
public virtual Paradigm Paradigm { get; set; }
}
public class Paradigm
{
[ScaffoldColumn(false)]
public int ParadigmId { get; set; }
[Required]
public string Name { get; set; }
public List<Entry> Entries { get; set; }
}
public class EntryViewModel
{
public Entry Entry { get; set; }
public IEnumerable<Entry> Entries { get; set; }
}
#model Pylon.Models.EntryViewModel
#{
ViewBag.Title = "Display";
}
<hr />
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Entry</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Entry.Description)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.Entry.Description)
#Html.ValidationMessageFor(model => model.Entry.Description)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Entry.ParadigmId)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Entry.ParadigmId, ((IEnumerable<Pylon.Models.Paradigm>)ViewBag.PossibleParadigms).Select(option => new SelectListItem {
Text = (option == null ? "None" : option.Name),
Value = option.ParadigmId.ToString(),
Selected = (Model != null) && (option.ParadigmId == Model.Entry.ParadigmId)
}))
<img src="../../Content/Images/add_icon.gif" />
#Html.ValidationMessageFor(model => model.Entry.ParadigmId)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
If I submit the form without entering a description I would like validation to kick in and say "You must include a description." However instead I receive an ArgumentNullException on the DropDownFor line. http://www.wvha.org/temp/ArgumentNullException.png
What should I be doing? As an aside any decent books that cover ASP.NET MVC 3/Razor. I can follow along the basic tuts, but I go astray when I need to deviate to more advance features.
public class EntriesController : Controller
{
private readonly PylonContext _context = new PylonContext();
public ActionResult Display()
{
// DropDown
ViewBag.PossibleParadigms = _context.Paradigms;
var viewModel = new EntryViewModel {Entries = _context.Entries.ToList()};
return View(viewModel);
}
[HttpPost]
public ActionResult Display(EntryViewModel viewModel)
{
if (ModelState.IsValid)
{
_context.Entries.Add(viewModel.Entry);
_context.SaveChanges();
return RedirectToAction("Display");
}
return View(viewModel);
}
}
It's quite difficult to say without seeing your controller code, but looks like your ViewBag.PossibleParadigms might be null.
Does your insert/update controller action look something like this?
if (ModelState.IsValid) {
///...
} else {
return View(model);
}
If so, you need to put the PossibleParadigms back into the ViewBag (so to speak) before you return back to the view.
If you can post the relevant controller action code, it would be easier to know for sure.