Get two tables data on a single MVC View - asp.net-mvc

I am not so much experienced with MVC in ASP.NET. Currently working on Visual Studio 2015 Community on a demo MVC project.
I am having difficulties having two tables combined in a view.
Following are two tables of concern from few tables.
I want to show data from both the tables at the same time in a single View(HTML Page).
TABLE - COMPLAIN
CREATE TABLE [dbo].[COMPLAIN](
[JOBSHEET_NO] [int] IDENTITY(1,1) NOT NULL,
[COMPANY_NAME] [nvarchar](50) NULL,
[MODEL_NAME] [nvarchar](50) NULL,
[IMEI_SRNO] [nvarchar](50) NULL,
[BATTERY_WITH_MOBILE] [nvarchar](50) NULL,
[MEMORYCARD_WITH_MOBILE] [nvarchar](50) NULL,
[FAULT_ID] [int] NOT NULL,
[CUSTOMER_NAME] [nvarchar](50) NULL,
[CUSTOMER_MOBILE] [nvarchar](50) NULL,
[ASSIGNED_TO_TECHNICIAN] [nvarchar](50) NULL,
[REMARKS] [nvarchar](500) NULL,
[CREATE_TIMESTAMP] [datetime] NULL,
[LAST_EDIT_TIMESTAMP] [datetime] NULL,
[IN_TIMESTAMP] [datetime] NULL,
[USER_ID] [nvarchar](50) NULL,
[ESTIMATE_AMOUNT] [float] NULL,
[ESTIMATE_AMOUNT_OK_FROM_CUSTOMER] [nvarchar](50) NULL,
[OUT_TIMESTAMP] [datetime] NULL,
[JOBSHEET_COMPLETE_STATUS] [nvarchar](50) NULL,
[NARRATION] [nvarchar](500) NULL,
CONSTRAINT [PK_COMPLAIN] PRIMARY KEY CLUSTERED
(
[JOBSHEET_NO] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
TABLE - REPAIRING
CREATE TABLE [dbo].[REPAIRING](
[JOBSHEET_NO] [int] NOT NULL,
[IN_TIMESTAMP] [datetime] NULL,
[CREATE_TIMESTAMP] [datetime] NULL,
[LAST_EDIT_TIMESTAMP] [datetime] NULL,
[ESTIMATE_AMOUNT] [float] NULL,
[ESTIMATE_AMOUNT_OK_FROM_CUSTOMER] [nvarchar](50) NULL,
[START_REPAIRING_TIMESTAMP] [datetime] NULL,
[END_REPAIRING_TIMESTAMP] [datetime] NULL,
[OUT_TIMESTAMP] [datetime] NULL,
[USER_ID] [nvarchar](50) NULL,
[NARRATION] [nvarchar](500) NULL,
CONSTRAINT [PK_REPAIRING] PRIMARY KEY CLUSTERED
(
[JOBSHEET_NO] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[REPAIRING] WITH CHECK ADD CONSTRAINT [FK_REPAIRING_COMPLAIN] FOREIGN KEY([JOBSHEET_NO])
REFERENCES [dbo].[COMPLAIN] ([JOBSHEET_NO])
GO
ALTER TABLE [dbo].[REPAIRING] CHECK CONSTRAINT [FK_REPAIRING_COMPLAIN]
GO
I am having FK relationship between those two tables.
I would also like to know if data from both the tables can be available without any FK relationship.
Following are my models.
COMPLAIN.cs
namespace WebMSM.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public partial class COMPLAIN
{
[Key]
[ReadOnly(true)]
[Required]
[DisplayName("JOBSHEET NO")]
public int JOBSHEET_NO { get; set; }
[Required]
[DisplayName("COMPANY NAME")]
public string COMPANY_NAME { get; set; }
[Required]
[DisplayName("MODEL NAME")]
public string MODEL_NAME { get; set; }
[Required]
[DisplayName("IMEI")]
public string IMEI_SRNO { get; set; }
[Required]
[DisplayName("BATTERY WITH MOBILE")]
public string BATTERY_WITH_MOBILE { get; set; }
[Required]
[DisplayName("MEMORY CARD WITH MOBILE")]
public string MEMORYCARD_WITH_MOBILE { get; set; }
[Required]
[DisplayName("FAULT")]
public int FAULT_ID { get; set; }
[Required]
[DisplayName("CUSTOMER NAME")]
public string CUSTOMER_NAME { get; set; }
[Required]
[DisplayName("CUSTOMER MOBILE")]
public string CUSTOMER_MOBILE { get; set; }
[Required]
[DisplayName("TECHNICIAN")]
public string ASSIGNED_TO_TECHNICIAN { get; set; }
[DisplayName("REMARKS")]
public string REMARKS { get; set; }
public Nullable<System.DateTime> CREATE_TIMESTAMP { get; set; }
public Nullable<System.DateTime> LAST_EDIT_TIMESTAMP { get; set; }
public Nullable<System.DateTime> IN_TIMESTAMP { get; set; }
[Required]
[DisplayName("USER ID")]
public string USER_ID { get; set; }
[DisplayName("ESTIMATE AMOUNT")]
public Nullable<double> ESTIMATE_AMOUNT { get; set; }
[DisplayName("ESTIMATE AMOUNT OK?")]
public string ESTIMATE_AMOUNT_OK_FROM_CUSTOMER { get; set; }
public Nullable<System.DateTime> OUT_TIMESTAMP { get; set; }
[DisplayName("STATUS")]
public string JOBSHEET_COMPLETE_STATUS { get; set; }
[Required]
[DisplayName("NARRATION")]
public string NARRATION { get; set; }
public virtual MASTER_FAULT MASTER_FAULT { get; set; }
public virtual REPAIRING REPAIRING { get; set; }
}
}
REPAIRING.cs
namespace WebMSM.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public partial class REPAIRING
{
[Required]
[DisplayName("JOBSHEET NO")]
public int JOBSHEET_NO { get; set; }
public Nullable<System.DateTime> IN_TIMESTAMP { get; set; }
public Nullable<System.DateTime> CREATE_TIMESTAMP { get; set; }
public Nullable<System.DateTime> LAST_EDIT_TIMESTAMP { get; set; }
[Required]
[DisplayName("ESTIMATE AMOUNT")]
public Nullable<double> ESTIMATE_AMOUNT { get; set; }
[Required]
[DisplayName("ESTIMATE AMOUNT OK?")]
public string ESTIMATE_AMOUNT_OK_FROM_CUSTOMER { get; set; }
[DisplayName("START REPAIR TIME")]
public Nullable<System.DateTime> START_REPAIRING_TIMESTAMP { get; set; }
[DisplayName("END REPAIR TIME")]
public Nullable<System.DateTime> END_REPAIRING_TIMESTAMP { get; set; }
[DisplayName("OUT TIME")]
public Nullable<System.DateTime> OUT_TIMESTAMP { get; set; }
public string USER_ID { get; set; }
[DisplayName("NARRATION")]
public string NARRATION { get; set; }
public virtual COMPLAIN COMPLAIN { get; set; }
}
}
Now I have created a RepairingController which displays list of COMPLAINs on its index View.
From that View, by Clicking 'Edit' link, I would like to go to Edit view in which data from both the tables about that record should be available.
Following is RepairingController.cs
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 WebMSM.Models;
namespace WebMSM.Controllers
{
public class RepairingController : Controller
{
private MSMContext db = new MSMContext();
// GET: Repairing
public ActionResult Index()
{
return View(db.COMPLAINs.ToList());
}
// GET: Repairing/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
REPAIRING rEPAIRING = db.REPAIRINGs.Find(id);
if (rEPAIRING == null)
{
return HttpNotFound();
}
return View(rEPAIRING);
}
// GET: Repairing/Create
public ActionResult Create()
{
return View();
}
// POST: Repairing/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 = "JOBSHEET_NO,IN_TIMESTAMP,CREATE_TIMESTAMP,LAST_EDIT_TIMESTAMP,ESTIMATE_AMOUNT,ESTIMATE_AMOUNT_OK_FROM_CUSTOMER,START_REPAIRING_TIMESTAMP,END_REPAIRING_TIMESTAMP,OUT_TIMESTAMP,USER_ID,NARRATION")] REPAIRING rEPAIRING)
{
if (ModelState.IsValid)
{
db.REPAIRINGs.Add(rEPAIRING);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(rEPAIRING);
}
// GET: Repairing/Edit/5
public ActionResult Edit(int? id)
{
var lstOKNOTOK = new List<SelectListItem>()
{
new SelectListItem {Text="OK",Value="OK" },
new SelectListItem {Text="NOT_OK",Value="NOT_OK" },
};
ViewBag.ESTIMATE_AMOUNT_OK_FROM_CUSTOMER = lstOKNOTOK;
REPAIRING rEPAIRING = db.REPAIRINGs.Find(id);
if (rEPAIRING == null)
{
return HttpNotFound();
}
return View(rEPAIRING);
}
// POST: Repairing/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 = "JOBSHEET_NO,IN_TIMESTAMP,CREATE_TIMESTAMP,LAST_EDIT_TIMESTAMP,ESTIMATE_AMOUNT,ESTIMATE_AMOUNT_OK_FROM_CUSTOMER,START_REPAIRING_TIMESTAMP,END_REPAIRING_TIMESTAMP,OUT_TIMESTAMP,USER_ID,NARRATION")] REPAIRING rEPAIRING)
{
if (ModelState.IsValid)
{
db.Entry(rEPAIRING).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(rEPAIRING);
}
// GET: Repairing/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
REPAIRING rEPAIRING = db.REPAIRINGs.Find(id);
if (rEPAIRING == null)
{
return HttpNotFound();
}
return View(rEPAIRING);
}
// POST: Repairing/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
REPAIRING rEPAIRING = db.REPAIRINGs.Find(id);
db.REPAIRINGs.Remove(rEPAIRING);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
Following is Edit.cshtml View For RepairingController.cs
#model WebMSM.Models.REPAIRING
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>REPAIRING</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.JOBSHEET_NO)
<div class="form-group">
#Html.LabelFor(model => model.JOBSHEET_NO, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.TextBoxFor(model => model.JOBSHEET_NO, new { #class = "form-control" ,#readonly="readonly"} )
#Html.ValidationMessageFor(model => model.JOBSHEET_NO, "", new { #class = "text-danger" })
</div>
</div>
#*<div class="form-group">
#Html.LabelFor(model => model.IN_TIMESTAMP, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.IN_TIMESTAMP, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.IN_TIMESTAMP, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CREATE_TIMESTAMP, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.CREATE_TIMESTAMP, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CREATE_TIMESTAMP, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LAST_EDIT_TIMESTAMP, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.LAST_EDIT_TIMESTAMP, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LAST_EDIT_TIMESTAMP, "", new { #class = "text-danger" })
</div>
</div>*#
<div class="form-group">
#Html.LabelFor(model => model.ESTIMATE_AMOUNT, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.ESTIMATE_AMOUNT, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ESTIMATE_AMOUNT, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ESTIMATE_AMOUNT_OK_FROM_CUSTOMER, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.DropDownListFor(model => model.ESTIMATE_AMOUNT_OK_FROM_CUSTOMER,ViewBag.ESTIMATE_AMOUNT_OK_FROM_CUSTOMER as SelectList, new { #class = "form-control" } )
#Html.ValidationMessageFor(model => model.ESTIMATE_AMOUNT_OK_FROM_CUSTOMER, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.START_REPAIRING_TIMESTAMP, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.START_REPAIRING_TIMESTAMP, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.START_REPAIRING_TIMESTAMP, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.END_REPAIRING_TIMESTAMP, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.END_REPAIRING_TIMESTAMP, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.END_REPAIRING_TIMESTAMP, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.OUT_TIMESTAMP, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.OUT_TIMESTAMP, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.OUT_TIMESTAMP, "", new { #class = "text-danger" })
</div>
</div>
#*<div class="form-group">
#Html.LabelFor(model => model.USER_ID, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.USER_ID, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.USER_ID, "", new { #class = "text-danger" })
</div>
</div>*#
<div class="form-group">
#Html.LabelFor(model => model.NARRATION, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.NARRATION, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.NARRATION, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-5 col-md-6">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Thanks in advance.

You should create a new view model class which has properties to represent data from both the tables
public class ComplaintDetailsVm
{
public Int JobSheetNo {set;get;}
public string CompanyName {set;get;}
public string CustomerName {set;get;}
public Decimal EsitmatedAmount {set;get;}
//Add other properties AS NEEDED
}
And use that for your view.
public ActionResult Edit(int id)
{
var vm = new ComplaintDetailsVm();
var r =db.REPAIRINGs.Find(id);
if(r!=null)
{
vm.JobSheetNo = r.JOBSHEET_NO;
vm.CustomerName= r.CUSTOMER_NAME;
//Map other properties here as needed
if(r.REPAIRING !=null)
{
vm.EstimatedAmount = r.ESTIMATED_AMOUNT;
//Map other properties here as needed
}
}
return View(vm);
}
And your view
#model ComplantDetailsVm
#using(Html.BeginForm())
{
#Html.TextBoxFor(s=>s.CompanyName)
#Html.TextBoxFor(s=>s.EstimatedAmount)
#Html.HiddenFor(s=>s.JobSheetNo)
<input type="submit" />
}
So when user posts the form, we need to read the data from our viewmodel object and use that for saving
[HttpPost]
public ActionResult Edit(ComplantDetailVm model)
{
if(ModelState.IsValid)
{
var e=db.COMPLAINs.FirstOrDefault(s=>s.JOBSHEET_NO==model.JobSheetNo);
if(e!=null)
{
// Update the property values
e.CompanyName = model.CompanyName;
//Map other properties also
db.Entry(e).State = EntityState.Modified;
db.SaveChanges();
//to do : Redirect to Success message page.
}
}
return View(model);
}

Related

Unable to edit the user information in mvc

Here is my problem , So i wanted to only allowing the user to change/edit their password and username only.
My original model for customer is this
public string IC { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Username{ get; set; }
public string Password{ get; set; }
And this is my VM for the customer
public string Username{ get; set; }
public string Password{ get; set; }
And this is my controller for the edit function
public ActionResult Edit([Bind(Include = "Username,Password")] CustomersVM customersVM )
{
if (ModelState.IsValid)
{
db.Entry(customersVM ).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(customersVM );
}
view.cshtml
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.IC)
<div class="form-group">
#Html.LabelFor(model => model.Username, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Username, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Username, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Password, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Password, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Password, "", new { #class = "text-danger" })
</div>
</div>
So this VM is to let the ModelState goes valid, which is will going right into the database but it turn out to turn this type of error
System.InvalidOperationException: 'The entity type CustomerVM is not part of the model for the current context.'
In order to edit/update a record, you need to identify that record first. I your case, your ViewModel is not what your database holds but the first model in your question. So you need to map that viewModel to the real model before saving or fetch the existing record then modify it then set it as modified before saving.
public ActionResult Edit([Bind(Include = "Username,Password")] CustomersVM customersVM )
{
if (ModelState.IsValid)
{
var existing = db.Customers.FirstOrDefault(x => x.Id == customersVM.Id);
if (existing != null)
{
existing.Username = customersVM.Username;
existing.Password = customerVM.Password;
db.Entry(existing ).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
}
return View(customersVM );
}

how i can send multivalue to create action

i have a doctor i want add doctor subspecialty to the doctor from sub specialties table many to many relationship
i need to add subspecialties from multiselect list but my controller only add first selection , i want my create controller take all passed subspecialties and create it
my model
public partial class DoctorSubSpecialty
{
public int Id { get; set; }
public Nullable<int> DoctorId { get; set; }
public Nullable<int> SubSpecialtyId { get; set; }
public virtual DoctorProfile DoctorProfile { get; set; }
public virtual SubSpecialty SubSpecialty { get; set; }
}
}
create get action
public ActionResult Create()
{
ViewBag.DoctorId = new SelectList(db.DoctorProfiles, "Id", "FullName");
ViewBag.SubSpecialtyId = new MultiSelectList(db.SubSpecialties, "id", "Name");
return View();
}
create post action
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "Id,DoctorId,SubSpecialtyId")] DoctorSubSpecialty doctorSubSpecialty)
{
DoctorSubSpecialty doctorSub = db.DoctorSubSpecialties.Where(d => d.DoctorId == doctorSubSpecialty.DoctorId & d.SubSpecialtyId == doctorSubSpecialty.SubSpecialtyId).FirstOrDefault();
if (doctorSub == null) {
db.DoctorSubSpecialties.Add(doctorSubSpecialty);
await db.SaveChangesAsync();
}
my view
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>DoctorSubSpecialty</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.DoctorId, "DoctorId", htmlAttributes: new { #class = "control-label col-md-2", #id = "DoctorID" })
<div class="col-md-10">
#Html.DropDownList("DoctorId", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.DoctorId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SubSpecialtyId, "SubSpecialtyId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("SubSpecialtyId",(MultiSelectList)ViewBag.SubSpecialtyId, htmlAttributes: new { #multiple = "multiple", #class = "form-control" })
#Html.ValidationMessageFor(model => model.SubSpecialtyId, "", 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>
}
Create a ViewModel specific to your usecase that can actually transport more than one Id.
I.e. you will need an int[] to bind the selection to.
A ViewModel also helps you to get rid of all this ViewBag and [Bind] nonsense.
public class CreateDoctorSubSpecialtyViewModel {
// These are the selected values to be posted back
public int DoctorId { get; set; }
public int[] SubSpecialtyIds { get; set; }
// These are the possible values for the dropdowns
public IEnumerable<SelectListItem> DoctorProfiles { get; set; }
public IEnumerable<SelectListItem> SubSpecialties { get; set; }
}
GET action - initialize the ViewModel and pass it to the View:
[HttpGet]
public ActionResult Create() {
var doctorProfiles = db.DoctorProfiles.Select(d =>
new SelectListItem {
Text = d.FullName,
Value = d.Id
}
).ToArray();
var subSpecialties = db.SubSpecialties.Select(s =>
new SelectListItem {
Text = s.Name,
Value = s.id
}
).ToArray();
var viewModel = new CreateDoctorSubSpecialtyViewModel {
DoctorProfiles = doctorProfiles,
SubSpecialties = subSpecialties
};
return View("Create", viewModel);
}
View "Create.cshtml" (styling removed for clarity) - tell MVC which ViewModel we want to use with #model:
#model CreateDoctorSubSpecialtyViewModel
#using (Html.BeginForm("Create", "YourControllerName", FormMethod.Post)) {
#Html.DropDownListFor(m => m.DoctorId, Model.DoctorProfiles)
#Html.DropDownListFor(m => m.SubSpecialtyIds, Model.SubSpecialties, new { multiple = "multiple" })
<input type="submit" />
}
POST action - use Linq Contains to test against multiple submitted SubSpecialtyIds:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(CreateDoctorSubSpecialtyViewModel postData) {
DoctorSubSpecialty[] allSelectedSubSpecialities = db.DoctorSubSpecialties
.Where(d => d.DoctorId == postData.DoctorId
&& postData.SubSpecialtyIds.Contains(d.SubSpecialtyId))
.ToArray();
// ...
}
EDIT #Html.DropDownListFor requires an IEnumerable<SelectListItem> as second parameter.

ID identity field value does not increase

I have a form to bind id field as hidden value. But in controller, the id (key, auto identity increment) field always 0. Below is my code:
Model.cs
public partial class A
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int id { get; set; }
[StringLength(255)]
[Display(Name = "Institution Name")]
[Required]
public string InstitutionName { get; set; }
[Display(Name = "Public")]
[DefaultValue(false)]
public bool Category1 { get; set; }
[Display(Name = "Private")]
[DefaultValue(false)]
[Display(Name = "Online")]
[DefaultValue(false)]
public bool Category3 { get; set; }
[
[Display(Name = "Active?")]
[DefaultValue(false)]
public bool active { get; set; }
public A()
{
Category1 = false;
Category2 = false;
Category3 = false;
active = true;
}
}
Controller:
...
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id,InstitutionName,Category1,Category2,Category3,active")] A A)
{
if (ModelState.IsValid)
{
db.A.Add(A);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(A);
}
}
...
View - Create.cshtml:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>TransferSearch_revised</h4>
<hr />
#Html.HiddenFor(model=> model.id)
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.InstitutionName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.InstitutionName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.InstitutionName, "", new { #class = "text-danger" })
</div>
</div>
...
The id value either 0 or empty. What's wrong with my code? Thanks.

Drop down list binding from another model in MVC

I am new to asp.net mvc
I have two tables tblEmployee and tblDepartment in both the tables common field is department id.
If the user creating new employee they have to select their department list from tblDepartment table.I am getting list of departments from that table there is no issue in that,but when i submitting the form departmentid is going null into the DB.
Models
public partial class Department
{
public Department()
{
this.tblEmployees = new HashSet<Employee>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Employee> tblEmployees { get; set; }
public Employee employee { get; set; }
}
public partial class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public string City { get; set; }
public Nullable<int> DepartmentId { get; set; }
public virtual Department tblDepartment { get; set; }
public List<Department> deprtment { get; set; }
public virtual string Department { get; set; }
public bool available { get; set; }
}
Controller:
public ActionResult Create()
{
SampleDbContext Db = new SampleDbContext();
List<Employee> employees = Db.Employees.Include("tblDepartment").ToList();
ViewBag.list = new SelectList(Db.Departments, "Id", "Name");
return View();
}
[HttpPost]
public ActionResult Create( Employee employee)
{
SampleDbContext Db = new SampleDbContext();
if (ModelState.IsValid)
{
Db.Employees.Add(employee);
Db.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
View:
#model EmployeeList.Models.Employee
....
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Employee</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
.... // controls for other properties of Employee
<div class="form-group">
#Html.LabelFor(model => model.DepartmentId, "DepartmentId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("list","select Depar")
#Html.ValidationMessageFor(model => model.DepartmentId, "", 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>
}

Button repeatedly calls GET method and does not POST when editing

I am trying to edit an entry in my database, but when I click submit, it just keeps calling the GET method over and over again and I cannot figure out why. I have tested this through breakpoints and there is no evidence of the POST method running - is it something to do with my Manufacturer binding?
Controller
// GET: Model/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Model model = db.Models.Find(id);
if (model == null)
{
return HttpNotFound();
}
ViewBag.Manufacturers = GetManufacturerList(model);
return View(model);
}
// POST: Model/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 EditPost(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var modelToUpdate = db.Models.Find(id);
if (TryUpdateModel(modelToUpdate, "",
new string[] { "ModelName", "ManufacturerID" }))
{
try
{
db.SaveChanges();
return RedirectToAction("Index");
}
catch (DataException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
}
ViewBag.Manufacturers = GetManufacturerList();
return View(modelToUpdate);
}
View:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Model</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.ModelID)
<div class="form-group">
#Html.LabelFor(model => model.ModelName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ModelName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ModelName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Manufacturer.ManufacturerName, "Manufacturer",
htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-5">
#Html.DropDownList("ManufacturerID", (List<SelectListItem>)ViewBag.Manufacturers,
htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Manufacturer.ManufacturerName, "",
new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
Models:
public class Model
{
[Required]
[Display(Name = "Manufacturer")]
[ForeignKey("Manufacturer")]
public int ManufacturerID { get; set; }
[Required]
public int ModelID { get; set; }
[Required]
[StringLength(50, ErrorMessage = "Model cannot be longer than 50 characters.")]
[RegularExpression(#"^[a-zA-Z0-9.-/() ]+$", ErrorMessage = "Invalid characters used. A-Z or a-z, 0-9, '.', '-', '()' and '/' allowed.")]
[Display(Name = "Model")]
public string ModelName { get; set; }
public virtual Manufacturer Manufacturer { get; set; }
public virtual ICollection<Item> Items { get; set; }
}
public class Manufacturer
{
[Required]
public int ManufacturerID { get; set; }
[Required]
[StringLength(50, ErrorMessage = "Manufacturer cannot be longer than 50 characters.")]
[RegularExpression(#"^[a-zA-Z0-9.-/() ]+$", ErrorMessage = "Invalid characters used. A-Z or a-z, 0-9, '.', '-', '()' and '/' allowed.")]
[Display(Name = "Manufacturer")]
public string ManufacturerName { get; set; }
public virtual ICollection<Model> Models { get; set; }
public virtual ICollection<Item> Items { get; set; }
}
Thanks in advance. Any help is greatly appreciated.
Your HttpPost method is named "EditPost". Shouldn't it be named simply "Edit" like this?
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Model model)
{
Here is a tutorial that might help you: https://www.asp.net/mvc/overview/older-versions/getting-started-with-aspnet-mvc4/examining-the-edit-methods-and-edit-view
Figured it out - I forgot to add the ActionName attribute as below:
[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public ActionResult EditPost(int? id)
{...}

Resources