Submit CheckBoxList From a single column in MVC .net - c#

I'm working in a HR project in ASP.NET MVC using Entity Framework with a database-first approach.
My view markup is:
<div class="form-group">
#Html.LabelFor(model => model.emp_Disease, htmlAttributes: new { #class = "control-label col-md-2 " })
<div class="col-md-10" style="padding-top:6px;margin:0px;">
#Html.CheckBoxListFor(m => m.emp_Disease,m=> m.Disease,s => s.Name, s => s.Name,s => s.emp_Disease,MvcCheckBoxList.Model.Position.Horizontal)
</div>
</div>
Controller action is:
[HttpPost]
public ActionResult Home(tbl_employee emp)
{
using (hrm_DB db = new hrm_DB())
{
if (emp.emp_Id == 0)
{
db.tbl_employee.Add(emp);
db.SaveChanges();
TempData["SaveMessage"] = "Save Record Succesfully! ";
}
else
{
db.Entry(emp).State = EntityState.Modified;
db.SaveChanges();
TempData["EditMessage"] = "Change Succesfully! ";
}
}
return RedirectToAction("ViewAll");
}
My model classes are:
public partial class tbl_employee
{
[DisplayName("AnyDisease")]
public string[] emp_Disease { get; set; }
public List<Checkdisease> Disease { get; set; }
}
public class Checkdisease
{
public int id { get; set; }
public string Name { get; set; }
public bool emp_Disease { get; set; }
}
Only store the one value. My problem is not submit the array store in database. How to store the string[] in database model ?

Related

Returning data to a view which has a model which references other models

So I have my model
public class AgencyAll
{
public Agency Agency { get; set; }
public AgencySector AgencySector { get; set; }
public AgencyExpertise AgencyExpertise { get; set; }
}
which acts a reference to other models so I can pass these into my view
Example - Agency model
public partial class Agency
{
public int id { get; set; }
public System.DateTime created { get; set; }
public int createdby { get; set; }
public string createdbytype { get; set; }
public System.DateTime lastupdated { get; set; }
public int lastupdatedby { get; set; }
public string lastupdatedbytype { get; set; }
public bool deleted { get; set; }
public string name { get; set; }
public string address { get; set; }
}
The AgencySector and AgencyExpertise are only contain the agency id and the other id (sector or expertise) as it's a many to many relationship
Part of my view
#model AgencyAll
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<div class="form-group">
Sector:
#Html.DropDownListFor(model => model.AgencySector.sectorid, (SelectList) ViewBag.SectorList, new {#class = "form-control"})
</div>
</div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<div class="form-group">
Specialisation:
#Html.DropDownListFor(model => model.AgencyExpertise.expertiseid, (SelectList) ViewBag.SpecialismList, new {#class = "form-control"})
</div>
</div>
As you can see, I can call the different models fine
My problem occurs here
public ActionResult ViewData(int id)
{
ViewBag.CountyList = new SelectList(GetCountyList(), "Value", "Text");
ViewBag.SectorList = new SelectList(GetSectorList(), "Value", "Text");
ViewBag.SpecialismList = new SelectList(GetSpecialisationList(), "Value", "Text");
return View(_db.Agencies.FirstOrDefault(x => x.id == id));
}
specifically, this line; return View(_db.Agencies.FirstOrDefault(x => x.id == id));
I am trying to return the agency data for the url ViewData/(id) however as the model for the view is AgencyAll, it cannot assign the dataset to the model as the model does not refer to a table, it refers to multiple models which refer to tables. The return statement is expecting the view to have the Agency model, not AgencyAll.
I cannot figure out what I need to replace return View(_db.Agencies.FirstOrDefault(x => x.id == id)); with in order to pass the data from the class to the model which has the model of the table, to show the data,
Any help would be much appreciated.
You need to be providing the expected model to your view, which is AgencyAll. At the moment you're providing an Agency object.
Change your code to something like this:
public ActionResult ViewData(int id)
{
ViewBag.CountyList = new SelectList(GetCountyList(), "Value", "Text");
ViewBag.SectorList = new SelectList(GetSectorList(), "Value", "Text");
ViewBag.SpecialismList = new SelectList(GetSpecialisationList(), "Value", "Text");
var viewModel = new AgencyAll {
Agency = _db.Agencies.FirstOrDefault(x => x.id == id),
AgencySector = _db.AgencySectors.FirstOrDefault(),
AgencyExpertise = _db.AgencyExpertises.FirstOrDefatul()
}
return View(viewModel);
}

Create/update in mvc using EF model not working

I am using an existing sql database in my MVC application. For one of the tables, the create/update functions do not work. I am assuming it is because my application fails to retrieve the auto generated ID's defined in SQL and hence inserts a null value into a non nullable field resulting in the application breaking. So, my question is how do i retrieved the auto generated fields defined in my sql database to show in my MVC5 application. Many thanks to anybody who can assist.
Below is my database table for Customers:
The Model:
public partial class Customer
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Customer()
{
this.Cards = new HashSet<Card>();
this.Stores = new HashSet<Store>();
}
public int CustomerID { get; set; }
public int DiscountLevelID { get; set; }
public int LoyaltyLevelID { get; set; }
public string CustomerCompanyName { get; set; }
public string CustomerName { get; set; }
public string CustomerSurname { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public string CustomerGUID { get; set; }
public int CustomerStatus { get; set; }
public string CustomerAddress { get; set; }
public string CustomerTel { get; set; }
public string CustomerCel { get; set; }
public Nullable<int> CustomerNumber { get; set; }
public string CustomerContact { get; set; }
public string CustomerLogo { get; set; }
public string CustomerLogoPath { get; set; }
public int LastStoreCustomerSyncID { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Card> Cards { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Store> Stores { get; set; }
}
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "CustomerID,DiscountLevelID,LoyaltyLevelID,CustomerCompanyName,CustomerName,CustomerSurname,CustomerGUID,CustomerStatus,CustomerAddress,CustomerTel,CustomerCel,CustomerNumber,CustomerContact,CustomerLogo,CustomerLogoPath,LastStoreCustomerSyncID")] Customer customer)
{
if (ModelState.IsValid)
{
db.Customers.Add(customer);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(customer);
}
// GET: Companies/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Customer customer = db.Customers.Find(id);
if (customer == null)
{
return HttpNotFound();
}
return View(customer);
}
// POST: Companies/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "CustomerID,DiscountLevelID,LoyaltyLevelID,CustomerCompanyName,CustomerName,CustomerSurname,CustomerGUID,CustomerStatus,CustomerAddress,CustomerTel,CustomerCel,CustomerNumber,CustomerContact,CustomerLogo,CustomerLogoPath,LastStoreCustomerSyncID")] Customer customer)
{
if (ModelState.IsValid)
{
db.Entry(customer).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(customer);
}
The View
<div class="form-group">
#Html.LabelFor(model => model.CustomerGUID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CustomerGUID, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CustomerGUID, "", new { #class = "text-danger" })
</div>
</div>
So, my question is how do i retrieved the auto generated fields
defined in my sql database to show in my MVC5 application.
Follow steps
Right click on the designer surface of the EDMX designer and click Update Model From Database...
All entities are refreshed by default, new entities are only added if you select them.
EDIT: If it is not refreshing well.
Select all the tables and view-s in the EDMX designer.
Delete them.
Then, update model from database
Right click On Model1.tt and select 'Run Custom Tool' save and Build Now see classes are generated.
Right click On Model1.Context.tt and select 'Run Custom Tool' save and Build Now see property IN Context class is generated like
P.S
Read this link also, it is very useful: http://blog.jongallant.com/2012/08/entity-framework-manual-update/
You should pass CustomerID to Controller as parameter. Don't give permission to CustomerID for null values and make it AUTO_INCREMENT
<div class="form-group">
#Html.TextBoxFor(model => model.CustomerID, new {style = 'display:none'})
#Html.LabelFor(model => model.CustomerGUID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CustomerGUID, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CustomerGUID, "", new { #class = "text-danger" })
</div>
</div>

Writing a list to database

For a school assignment I need to make a poll with ASP.NET
The problem I get when trying to write the answers in the database is that only one question and one answer gets written into it.
This is the View
#model CinemaJamV2.WebUIV2.Models.EnqueteModel
#{
ViewBag.Title = "Enquete";
}
<h2>Enquete</h2>
#Html.ValidationSummary(true)
#using (Html.BeginForm("Enquete", "Enquete", new { vraag = "vraag", antwoord = "antwoord", naam = "naam", cijfer = "cijfer" }))
{
<div class="col-md-12">
#for(var i=0;i< Model.enquetevragen.Count();i++)
{
<div class="thumbnail">
#Html.LabelFor(model => model.enquetevragen[i].vraag, new { htmlAttributes = new { #class = "form-control" } })
#Html.EditorFor(model => model.enquete.antwoord, new { htmlAttributes = new { #class = "form-control" } })
#Html.EditorFor(model => model.enquete.cijfer, new { htmlAttributes = new { #class = "form-control" } })
</div>
}
</div>
<div class="col-md-12">
<p>Naam <input type="text" name="naam" /> </p>
<input type="submit" name="submit" value="Verzend" />
</div>
}
This is the Controller:
namespace CinemaJamV2.WebUIV2.Controllers
{
public class EnqueteController : Controller
{
private IRepository<Enquete> repository;
private IRepository<EnqueteVraag> a_repository;
private CineJamContext db = new CineJamContext();
public EnqueteController(IRepository<Enquete> a_model, IRepository<EnqueteVraag> vraag_model)
{
repository = a_model;
a_repository = vraag_model;
}
[HttpGet]
public ActionResult Enquete()
{
EnqueteModel enquetevragen = new EnqueteModel
{
enquetevragen = a_repository.List
};
return View(enquetevragen);
}
[HttpPost]
public ActionResult Enquete(Enquete enquete)
{
if (ModelState.IsValid)
{
db.Enquetes.Add(enquete);
db.SaveChanges();
return RedirectToAction("Enquete");
}
return View(enquete);
}
}
}
The ModelView:
namespace CinemaJamV2.WebUIV2.Models
{
public class EnqueteModel
{
public List<Enquete> enquetes {get; set;}
public Enquete enquete { get; set; }
public List<EnqueteVraag> enquetevragen { get; set; }
}
}
And this is the Model Enquete which should contain all the given answers:
namespace CinemaJamV2.Domain.Entities
{
[Table("Enquete")]
public partial class Enquete : IEntity
{
public int Id { get; set; }
[StringLength(1000)]
public string vraag { get; set; }
[StringLength(1000)]
//[Required]
public string antwoord { get; set; }
public int? cijfer {get; set;}
[StringLength(50)]
//[Required]
public string naam { get; set; }
}
}
This Model contains all the Questions
namespace CinemaJamV2.Domain.Entities
{
[Table("EnqueteVraag")]
public partial class EnqueteVraag : IEntity
{
public int Id { get; set; }
[StringLength(1000)]
public string vraag { get; set; }
}
}
The action for POST has only one instance of the Model as its parameter. You need to read this: Model binding to a list
YOu need to use view model that will have list of Enquete and then in post method again you need to do for loop and save it to database.
See following links for samples.
http://www.binaryintellect.net/articles/b1e0b153-47f4-4b29-8583-958aa22d9284.aspx
http://www.c-sharpcorner.com/UploadFile/pmfawas/Asp-Net-mvc-how-to-post-a-collection/
http://www.codeproject.com/Tips/855577/List-of-Model-Object-Post-to-Controller-in-ASP-NET

Proper way to populate a ViewModel?

I'm working on a webapp for work, and I'm using standard CRUD style interactions. However, there are certain fields that I do not want the users updating, so I removed them from the view. However, if I don't explicitly set these fields, they're cleared when the model is updated in the database.
I'm concerned with what the proper method of populating the fields for my ViewModels is.
The rough idea I came up with was something like this:
My view model:
public class EditSoftwareTrackingViewModel
{
public EditSoftwareTrackingViewModel(SoftwareTracking model)
{
Id = model.Id;
SoftwareId = model.SoftwareId;
ComputerId = model.ComputerId;
SoftwareActionId = model.SoftwareActionId;
LastModified = model.LastModified;
Computer = model.Computer;
Software = model.Software;
SoftwareAction = model.SoftwareAction;
}
public int Id { get; set; }
[DisplayName("Software")]
public int SoftwareId { get; set; }
[DisplayName("Computer")]
public int ComputerId { get; set; }
[DisplayName("Software Action")]
public int SoftwareActionId { get; set; }
[DisplayName("Last Modified")]
public DateTime? LastModified { get; set; }
public virtual Computer Computer { get; set; }
public virtual Software Software { get; set; }
public virtual SoftwareAction SoftwareAction { get; set; }
}
My main model
[Table("asset.SoftwareTracking")]
public partial class SoftwareTracking
{
public int Id { get; set; }
[DisplayName("Software")]
public int SoftwareId { get; set; }
[DisplayName("Computer")]
public int ComputerId { get; set; }
[DisplayName("Date Entered")]
public DateTime? EnteredDate { get; set; }
[DisplayName("Software Action")]
public int SoftwareActionId { get; set; }
[DisplayName("Last Modified")]
public DateTime? LastModified { get; set; }
public virtual Computer Computer { get; set; }
public virtual Software Software { get; set; }
public virtual SoftwareAction SoftwareAction { get; set; }
}
And my controller using the view model
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
EditSoftwareTrackingViewModel softwaretracking = new EditSoftwareTrackingViewModel(db.SoftwareTrackings.Find(id));
if (softwaretracking == null)
{
return HttpNotFound();
}
GeneratePageData(softwaretracking.Software.Id);
return View(softwaretracking);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(EditSoftwareTrackingViewModel softwaretracking)
{
if (ModelState.IsValid)
{
softwaretracking.LastModified = DateTime.Now;
var softwareTrack = db.SoftwareTrackings.Find(softwaretracking.Id);
softwareTrack = new SoftwareTracking
{
Computer = softwaretracking.Computer,
ComputerId = softwaretracking.ComputerId,
LastModified = softwaretracking.LastModified,
Software = softwaretracking.Software,
SoftwareAction = softwaretracking.SoftwareAction,
SoftwareActionId = softwaretracking.SoftwareActionId,
SoftwareId = softwaretracking.SoftwareId,
EnteredDate = softwareTrack.EnteredDate
};
db.Entry(softwareTrack).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
GeneratePageData(softwaretracking.Software.Id);
return View(softwaretracking);
}
Is there a better alternative? Or should I continue to create my view models in this manner?
EDIT
My business logic and view
private void GeneratePageData(int? id = null)
{
ViewBag.Computers = new SelectList(db.Computers, "Id", "ComputerName");
ViewBag.SoftwareActions = new SelectList(db.SoftwareActions, "Id", "ActionPerformed");
var usedSoft = (from softTrack in db.SoftwareTrackings
where (softTrack.SoftwareActionId != 3)
select softTrack.Software);
var softwareList = (from soft in db.Softwares
where (
((from softTrack in db.SoftwareTrackings
where (softTrack.SoftwareActionId != 3 && softTrack.SoftwareId == soft.Id)
select softTrack.Software).Count() < soft.KeyQuantity)
&& !(soft.AssetStatusId == 4 || soft.AssetStatusId == 5)
|| soft.Id == id)
select soft).ToList();
ViewBag.SoftwareList = softwareList.Select(t => new SelectListItem
{
Text = t.SoftwareIdNameFull,
Value = t.Id.ToString()
});
}
And my view
#model Lighthouse_Asset_Manager.Models.EditSoftwareTrackingViewModel
#{
ViewBag.Title = "Edit Software Install";
Layout = "";
}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
×
</button>
<h4 class="modal-title" id="myModalLabel">Edit Software Install</h4>
</div>
<div class="modal-body">
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "computerForm" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.Id)
<div class="form-horizontal">
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.SoftwareId, "Software", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("SoftwareId", (IEnumerable<SelectListItem>)ViewBag.SoftwareList, "-- Select --", new
{
#style = "width:100%",
#class = "select2"
})
#Html.ValidationMessageFor(model => model.SoftwareId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ComputerId, "Computer", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("ComputerId", (IEnumerable<SelectListItem>)ViewBag.Computers, "-- Select --", new
{
#style = "width:100%",
#class = "select2"
})
#Html.ValidationMessageFor(model => model.ComputerId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SoftwareActionId, "Action", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("SoftwareActionId", (IEnumerable<SelectListItem>)ViewBag.SoftwareActions, "-- Select --", new
{
#style = "width:100%",
#class = "form-control"
})
#Html.ValidationMessageFor(model => model.SoftwareActionId)
</div>
</div>
<div class="form-actions no-color">
<button type="submit" class="btn btn-primary btn-sm"><i class="fa fa-floppy-o"></i> Edit Install Record</button>
<button type="button" class="btn btn-default" data-dismiss="modal">
Cancel
</button>
</div>
</div>
}
</div>
You approach of using a view model is a good one. The answers to this question explains some of the benefits including preventing over-posting attacks, using view specific display and validation attributes and including view specific properties such as SelectLists. Tools such as automapper can make it easy to map between you data and view models and reduce the code in the controller. A few changes I would suggest to your view model. The LastModified, Computer, Software and SoftwareAction properties are not required (you not binding to these), and I would include the SelectList properties in the model rather than ViewBag
View model
public class EditSoftwareTrackingViewModel
{
public int Id { get; set; }
[Display(Name="Software")]
public int SoftwareId { get; set; }
[Display(Name="Computer")]
public int ComputerId { get; set; }
[Display(Name="Software Action")]
public int SoftwareActionId { get; set; }
public SelectList Computers { get; set; }
public SelectList SoftwareActions{ get; set; }
public SelectList SoftwareList{ get; set; }
}
Then change the GeneratePageData() method to accept the view model
private void GeneratePageData(EditSoftwareTrackingViewModel model)
{
model.Computers = new SelectList(db.Computers, "Id", "ComputerName");
....
and in the view (always preferable to use the strongly typed helpers)
#Html.DropDownListFor(m => m.SoftwareId, Model.SoftwareList, "-- Select --", new { #class = "select2" })
A few other things to note.
You should use the [Display(Name="..")] attribute (not
[DisplayName(..)])
When you set the LastModified property, you should consider using
UCT time.
The hidden input for the Id property is not required in the view
(assuming your using the default {controller}/{action}/{id} route
mapping) - its added to the route values and will be bound anyway
Unless you specifically want an id attribute for the form, you can
just use #using(Html.BeginForm()) {
You do not need the second parameter in LabelFor() - it can be just
Html.LabelFor(m => m.SoftwareId, new { #class = "control-label
col-md-2" }) since you have specified it in the [Display]
attribute
Finally, if you want to simplify your view further, you could consider custom EditorTemplates or html helpers as indicated in this answer which would allow you to replace
<div class="form-group">
#Html.LabelFor(model => model.SoftwareId, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.SoftwareId, Model.SoftwareList, "-- Select --", new { #class = "select2" })
#Html.ValidationMessageFor(model => model.SoftwareId)
</div>
</div>
with (custom EditorTemplate)
#Html.EditorFor(m => m.SoftwareId, "BootstrapSelect", Model.SoftwareList)
or (custom HtmlHelper)
#Html.BootstrapDropDownFor(m => m.SoftwareId, Model.SoftwareList)
You should use the AutoMapper to make the mapping between Model and ViewModel cleaner. Use this code to create the mapper first.
Mapper.CreateMap<SoftwareTracking, EditSoftwareTrackingViewModel>();
Mapper.CreateMap<EditSoftwareTrackingViewModel, SoftwareTracking>();
When you want to create a viewmodel from model, do this:
public ActionResult Edit(int? id)
{
SoftwareTracking tracking = db.SoftwareTrackings.Find(id);
EditSoftwareTrackingViewModel viewmodel =
Mapper.Map<SoftwareTracking, EditSoftwareTrackingViewModel>(tracking);
return View(viewmodel);
}
When you want to populate the info from the viewmodel back to the model, do this
public ActionResult Edit(EditSoftwareTrackingViewModel vm)
{
if (ModelState.IsValid)
{
vm.LastModified = DateTime.Now;
var softwareTrack = db.SoftwareTrackings.Find(softwaretracking.Id);
softwareTrack =
Mapper.Map<EditSoftwareTrackingViewModel, SoftwareTracking>(vm, softwareTrack);
db.Entry(softwareTrack).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
To patch update your model without loading the object from Db. Try Attach:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(EditSoftwareTrackingViewModel softwaretracking)
{
if (ModelState.IsValid)
{
var softwareTrack = new SoftwareTracking
{
Computer = softwaretracking.Computer,
ComputerId = softwaretracking.ComputerId,
LastModified = softwaretracking.LastModified,
Software = softwaretracking.Software,
SoftwareAction = softwaretracking.SoftwareAction,
SoftwareActionId = softwaretracking.SoftwareActionId,
SoftwareId = softwaretracking.SoftwareId,
EnteredDate = softwareTrack.EnteredDate
};
db.SoftwareTrackings.Attach(softwareTrack);
db.Entry(softwareTrack).Property(a => a.Computer).IsModified = true;
db.Entry(softwareTrack).Property(a => a.ComputerId).IsModified = true;
db.Entry(softwareTrack).Property(a => a.LastModified).IsModified = true;
db.Entry(softwareTrack).Property(a => a.Computer).IsModified = true;
db.Entry(softwareTrack).Property(a => a.Software).IsModified = true;
db.Entry(softwareTrack).Property(a => a.SoftwareAction).IsModified = true;
db.Entry(softwareTrack).Property(a => a.SoftwareActionId).IsModified = true;
db.Entry(softwareTrack).Property(a => a.SoftwareId).IsModified = true;
db.SaveChanges();
return RedirectToAction("Index");
}
GeneratePageData(softwaretracking.Software.Id);
return View(softwaretracking);
}
Regarding the second question about whether to use ViewModel or just use the Model directly. This is really a matter of opinion, each approach has its pros and cons. I don't have strong opinion about this, i just want to point out these pros and cons for your consideration:
Using the model directly saves us from creating the viewModel, resulting in smaller source code and avoiding mapping logic but it would mix concerns. Because you use the same Model for your domain logic and for communcating with the client, any changes to the model may propagate up to the client if we don't take that into account.
Using the viewModel is a good way for separation of concerns but it would require more effort and mapping logic (maybe slow down the performance a bit). To apply ViewModel efficiently, I suggest using a mapper: https://github.com/AutoMapper/AutoMapper/wiki/Getting-started
This is the Model Class
[Table("CURRENCY")]
public class CurrencyClass : ICurrency
{
private Int32 mCURRENCY_ID = default(Int32);
[Key]
public virtual Int32 CURRENCY_ID
{
get { return mCURRENCY_ID; }
set { mCURRENCY_ID = value; }
}
private string mCURRENCY_NAME = default(string);
public virtual string CURRENCY_NAME
{
get { return mCURRENCY_NAME;}
set { mCURRENCY_NAME = value;}
}
private string mCURRENCY_DESC = default(string);
public virtual string CURRENCY_DESC
{
get { return mCURRENCY_DESC; }
set { mCURRENCY_DESC = value; }
}
private string mCURRENCY_SYMBOLE = default(string);
public virtual string CURRENCY_SYMBOLE
{
get { return mCURRENCY_SYMBOLE; }
set { mCURRENCY_SYMBOLE = value; }
}
private Int32 mcreated_by = default(Int32);
public virtual Int32 created_by
{
get { return mcreated_by; }
set { mcreated_by = value; }
}
private DateTime mcreated_date = default(DateTime);
public virtual DateTime created_date
{
get { return mcreated_date; }
set { mcreated_date = value; }
}
private Int32 mmodified_by = default(Int32);
public virtual Int32 modified_by
{
get { return mmodified_by; }
set { mmodified_by = value; }
}
private DateTime mmodified_date = default(DateTime);
public virtual DateTime modified_date
{
get { return mmodified_date; }
set { mmodified_date = value; }
}
}
This is the ViewModel
public class CurrencyViewModel
{
[Key]
public Int32 CURRENCY_Id { get; set; }
[Required(ErrorMessage="Currency Name is required")]
public string CURRENCY_NAME { get; set; }
[Required(ErrorMessage="Currency Description is required")]
public string CURRENCY_DESC { get; set; }
[Required(ErrorMessage = "Currency Symbole is Required")]
public string CURRENCY_SYMBOLE { get; set; }
}
This is the Action
[HttpPost]
[ActionName("Create")]
public ActionResult Create(CurrencyViewModel vm)
{
if (!ModelState.IsValid)
{
return View("Create");
}
obj.CURRENCY_NAME = vm.CURRENCY_NAME;
obj.CURRENCY_DESC = vm.CURRENCY_DESC;
obj.CURRENCY_SYMBOLE = vm.CURRENCY_SYMBOLE;
obj.created_by = 1;
obj.created_date = DateTime.Now;
obj.modified_by = 1;
obj.modified_date = DateTime.Now;
db.Currencies.Add(obj);
db.SaveChanges();
return RedirectToAction("Index");
}

Save newly created object ASP.NET MVC

I'm using EF Code First and here is my class which references a Professor object.
public class Mark
{
public int MarkId { get; set; }
[Required(ErrorMessage = "Please provide Grade")]
[Display(Name = "Grade Value")]
public int MarkValue { get; set; }
[Required(ErrorMessage = "Please provide grade type")]
[Display(Name = "Grade Type")]
public string Type { get; set; }
[Required(ErrorMessage = "Please provide Subject")]
[Display(Name = "Subject")]
public virtual Subject Subject { get; set; }
public virtual User User { get; set; }
public virtual Professor Professor { get; set; }
}
In my view I have a dropdown to select a professor who put the mark.
I implemented it like this:
//controller
public MarksController() : this(new MarkRepository())
{
IProfessorRepository professorsRepo = new ProfessorRepository();
List<Professor> professors = professorsRepo.All.ToList<Professor>();
List<SelectListItem> items = new List<SelectListItem>();
foreach (Professor p in professors)
{
items.Add(new SelectListItem
{
Text = String.Concat(p.FirstName, " ", p.LastName), Value = p.ProfessorId.ToString()
});
}
items.Add(new SelectListItem
{
Text = "Please select Professor", Value = "0", Selected = true
});
ViewBag.Professors = items;
}
//view create or edit
<div class="editor-label">
#Html.LabelFor(model => model.MarkValue)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.MarkValue)
#Html.ValidationMessageFor(model => model.MarkValue)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Type)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Type)
#Html.ValidationMessageFor(model => model.Type)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Professor)
</div>
<div class="editor-field">
#Html.DropDownList("Professors");
</div>
Yes, I know that there is is a metod in Controller called Create which appeals repository method InsertOrUpdate.
[HttpPost]
public ActionResult Create(Mark mark)
{
if (ModelState.IsValid) {
markRepository.InsertOrUpdate(mark);
markRepository.Save();
return RedirectToAction("Index");
} else {
return View();
}
}
public void InsertOrUpdate(Mark mark)
{
if (mark.MarkId == default(int)) {
// New entity
context.Marks.Add(mark);
} else {
// Existing entity
context.Entry(mark).State = EntityState.Modified;
}
}
Everything seems logic, but how can I save a newly created Mark object with the professor selected? How does ASP.NET arranges the object which is passed to Create method on Controller? How should I match the selected professor with the mark I am creating?
Take a look at this, you need a ProfessorId in the model.
Model binding dropdown selected value
public class Mark
{
// this will hold the selected value
public string ProfessorID { get; set; }
public IEnumerable<SelectListItem> Professors
{
get
{
return Proffessors
.Select(x => new SelectListItem {
Value = x.ProfessorId.ToString(),
Text = String.Concat(p.FirstName, " ", p.LastName)
});
}
}
public IEnumerable<Professor> Proffessors
{
get
{
IProfessorRepository professorsRepo = new ProfessorRepository();
return professorsRepo.All;
}
}
//the rest of your code
}
in the view do
#Html.DropDownListFor(
x => x.ProfessorId,
new SelectList(Model.Professors, "Value", "Text")
)

Categories

Resources