Editing and saving from a ViewModel. - c#

This seems to be a common question. I have looked at many examples however I must be missing something somewhere. Below is my code for the 'ViewModel', and 'Controller'.
ViewModel:
public class EditAddressViewModel
{
public Guid AddressUI { get; set; }
[Display(Name = "Billing Address?")]
[UIHint("_IsStatus")]
public bool IsBilling { get; set; }
[Display(Name = "Shipping Address?")]
[UIHint("_IsStatus")]
public bool IsShipping { get; set; }
[Display(Name = "Location Name")]
public string LocationName { get; set; }
[Display(Name = "Contact Name")]
public string ContactName { get; set; }
[Display(Name = "Address")]
public string Line1 { get; set; }
[Display(Name = "Address 2")]
public string Line2 { get; set; }
[Display(Name = "Country")]
public int Country { get; set; }
[Display(Name = "State")]
public int State { get; set; }
[Display(Name = "City")]
public int City { get; set; }
[Display(Name = "ZipCode")]
public string ZipCode { get; set; }
[Display(Name = "Contact Email")]
[DataType(DataType.EmailAddress)]
[StringLength(320)]
[RegularExpression(#"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", ErrorMessage = "Enter a valid email address")]
public string EmailAddress { get; set; }
[Display(Name = "Phone Number")]
[DataType(DataType.PhoneNumber)]
[StringLength(12)]
[RegularExpression(#"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}", ErrorMessage = "Enter a valid phone number")]
public string PhoneNumber { get; set; }
[Display(Name = "Fax Number")]
[DataType(DataType.PhoneNumber)]
[StringLength(12)]
[RegularExpression(#"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}", ErrorMessage = "Enter a valid phone number")]
public string FaxNumber { get; set; }
public int CompanyId { get; set; }
[Display(Name = "Select Country")]
public int CountryId { get; set; }
public IEnumerable<SelectListItem> Countries { get; set; }
[Display(Name = "Select State")]
public int StateId { get; set; }
public IEnumerable<SelectListItem> States { get; set; }
[Display(Name = "Select Cit;y")]
public int CityId { get; set; }
public IEnumerable<SelectListItem> Cities { get; set; }
}
The Controller:
// Customer Input
// GET: Addresses/Edit/5
[Authorize(Roles = "CompanyAdmin")]
public ActionResult UserEdit(Guid guid)
{
if (guid == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Addresses addresses = db.Addresses.Find(guid);
if (addresses == null)
{
return HttpNotFound();
}
EditAddressViewModel editAddress = new EditAddressViewModel()
{
AddressUI = addresses.AddressUI,
LocationName = addresses.LocationName,
Line1 = addresses.Line1,
Line2 = addresses.Line2,
Country = addresses.Country,
State = addresses.State,
City = addresses.City,
ZipCode = addresses.ZipCode,
PhoneNumber = addresses.PhoneNumber,
FaxNumber = addresses.FaxNumber,
CompanyId = addresses.CompanyId
};
ConfigureViewModel(editAddress);
return View(editAddress);
}
public void ConfigureViewModel(EditAddressViewModel editAddressViewModel)
{
editAddressViewModel.Countries = db.Countries.Select(o => new SelectListItem()
{
Value = o.CountryId.ToString(),
Text = o.CountryName
});
editAddressViewModel.States = db.States.Select(o => new SelectListItem()
{
Value = o.StateId.ToString(),
Text = o.StateName
});
editAddressViewModel.Cities = db.Cities.Select(o => new SelectListItem()
{
Value = o.CityId.ToString(),
Text = o.CityName
});
}
// POST: Addresses/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UserEdit(EditAddressViewModel model)
{
var userId = User.Identity.GetUserId();
if (!ModelState.IsValid)
{
return View(model);
}
Addresses addresses = db.Addresses.Find(model.AddressUI);
addresses.IsBilling = EditAddressViewModel.IsBilling;
addresses.IsShipping = EditAddressViewModel.IsShipping;
addresses.LocationName = EditAddressViewModel.LocationName;
addresses.Line1 = EditAddressViewModel.Line1;
addresses.Line2 = EditAddressViewModel.Line2;
addresses.Country = EditAddressViewModel.Country;
addresses.State = EditAddressViewModel.State;
addresses.City = EditAddressViewModel.City;
addresses.ZipCode = EditAddressViewModel.ZipCode;
addresses.PhoneNumber = EditAddressViewModel.PhoneNumber;
addresses.FaxNumber = EditAddressViewModel.FaxNumber;
addresses.CompanyId = EditAddressViewModel.CompanyId;
db.Entry(addresses).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index", "Customer", new { UserId = userId });
}
The issue I am running into is in the controller. All of the entries for Example
addresses.IsBilling = EditAddressViewModel.IsBilling;
Show that "An object reference is required for the non-static field, method, or property". If I go to my 'ViewModel' and change the "public int or string" to be "public static int" then it goes away but then I get an error on the get Action that is cannot be tied to a static object. I am a little confused because this same scenario seems to work for another question on this site. In mine it does not. I have to be missing something somewhere. thanks for your help.

When you say addresses.IsBilling = EditAddressViewModel.IsBilling; you are asking for a property of the class EditAddressViewModel
You want to access a property of the object model. So I think you want addresses.IsBilling = model.IsBilling; etc.

Related

Blazor UI issue, how do I force the required error message on my dropdown select statement when user does not select an option?

I am using Blazor UI. here is my Dropdown markup:
The issue I am referring to is that if the user does NOT make a selection, in other words the _bid.ProductLineId is null and the default "Select a Product Line" is displayed, the [Required] property in the Model (BidViewModel) should fire the message: Product Line is required, but it does not. The on change method is firing, but not the message. Any suggestions?
<ContentTemplate>
<EditForm Model="#_bid" OnValidSubmit="#SaveBid" class="animate-fade" Context="editFrmBidConfirmation">
<DataAnnotationsValidator />
<ServerValidator #ref="serverValidator" />
<ValidationSummary />
<BSContainer>
<BSRow>
<BSCol MD="2" Class="form-label">Product Line:</BSCol>
<BSCol MD="4">
<select id="ProductLine" #onchange="#ProductLineChange" value="#_bid.ProductLineId">
<option value=null>Select a Product Line</option>
#foreach (ProductLine a in _productLines)
{
<option value="#a.Id">#a.Name</option>
}
</select>
</BSCol>
Here is the initialization:
private BidViewModel _bid { get; set; }
private List<Data.Models.ProductLine> _productLines { get; set; }
_productLines = await processor.ProcessObject<List<Data.Models.ProductLine>>(await apiClient.GetProductLinesForUserAsync(userId));
_productLineSelected = (_bid.ProductLineId != null);
Here is the method to fire on change: #ProductLineChange, note "e" is null, thus _bid.ProductLineId is set to null in the BidViewModel.
private async Task ProductLineChange(ChangeEventArgs e)
{
_bid.ProductLineId = e.Value.ToString();
_productLineSelected = (!string.IsNullOrEmpty(_bid.ProductLineId));
if (!string.IsNullOrEmpty(_bid.ProductLineId))
{
_bidClasses = await processor.ProcessObject<List<Bid_Class>>(await apiClient.GetBidClassesAsync(_bid.ProductLineId));
_bidStatuses = await processor.ProcessObject<List<Bid_StatusViewModel>>(await apiClient.GetBidStatusesAsync(_bid.ProductLineId));
_bidTypes = await processor.ProcessObject<List<Bid_Type>>(await apiClient.GetBidTypesAsync(_bid.ProductLineId));
_distributorGroups = new();
_distributors = await processor.ProcessObject<List<DistributorViewModel>>(await apiClient.GetDistributorsByProductLineAsync(_bid.ProductLineId));
}
RefreshScreen(null);
}
Lastly Here is the ViewModel: BidViewModel
public class BidViewModel : Bid
{
public BidViewModel()
{
Notes_Internal = new List<BidNoteInternal>();
Notes_Pricing = new List<BidNotePricing>();
Items = new List<Bid_Item>();
Bid_Locations = new List<Bid_Location>(); //11/30/2021 SEO 681529
Bid_Distributor_Entities = new List<Bid_Distributor_Entity>(); //03/20/2022 SEO 681533
}
// 12/22/2022 PTR 1060058 - Resolve Framework Warning, always start with Capital
public bool IsExisting { get; set; }
public bool Equals(Bid other)
{
if (this.Id == other.Id)
{
return true;
}
else
{
return false;
}
}
}
Bid class which is inherited by BidViewModel:
namespace BQM.Data.Models
{
[Display(Name = "Bid")]
public class Bid : BaseAuditEntity<string>, IValidatableObject
{
public Bid()
{
Id = "Generated";
DateCreated =
DateModified =
Date_BidOpened = DateTime.Now.Date; //09/22/2021 SEO 786208 - Strip time portion to allow for proper filter
Date_BidPriceStart = DateTime.Now;
Distributor_GroupId = "";
DistributorId = "";
Notes_Internal = new List<BidNoteInternal>();
Notes_Pricing = new List<BidNotePricing>();
Items = new List<Bid_Item>();
SalesPeople = new List<BidToSalesPeople>();
IsPercentageOff = false;
Active = true;
IsQuote = false;
PercentageOff = 0;
ProgramAdjustment = false;
//11/30/2021 SEO 681529
Bid_Locations = new List<Bid_Location>();
//03/20/2022 SEO 681533
Bid_Distributor_Entities = new List<Bid_Distributor_Entity>();
}
[Key]
[Required(ErrorMessage = "Bid ID is required.")]
[Display(Name = "New Bid #")]
[Column("BidId")]
[StringLength(10, ErrorMessage = "The New Bid # can only be 10 characters (or less)")]
public override string Id { get; set; }
[Display(Name = "Old Bid #")]
[StringLength(10, ErrorMessage = "The Old Bid # can only be 10 characters (or less)")]
public string OldBidNumber { get; set; }
[Required(ErrorMessage = "Bid Type is required.")]
public string Bid_TypeId { get; set; }
[Display(Name = "Bid Type")]
public virtual Bid_Type Bid_Type { get; set; }
[Required(ErrorMessage = "Bid Class is required.")]
public string Bid_ClassId { get; set; }
[Display(Name = "Bid Class")]
public virtual Bid_Class Bid_Class { get; set; }
[Required(ErrorMessage = "Product Line is required.")]
public string ProductLineId { get; set; }
[Display(Name = "Product Line")]
public virtual ProductLine ProductLine { get; set; }
[Required(ErrorMessage = "Account Name is required.")]
[StringLength(75, ErrorMessage = "Account Name can't be longer than 75 characters")]
public string Account { get; set; }
//09/16/2021 SEO - Added distributed group requirement
[Required(ErrorMessage = "Distributor Group is required.")]
public string Distributor_GroupId { get; set; }
public virtual Distributor_Group Distributor_Group { get; set; }
[Required(ErrorMessage = "Distributor is required.")]
[Display(Name = "Distributor #")]
public string DistributorId { get; set; }
public virtual Distributor Distributor { get; set; }
[Required(ErrorMessage = "Sales Rep. is required.")]
public string SalesPersonDefaultId { get; set; }
[Display(Name = "Sales Rep.")]
public virtual SalesPerson SalesPersonDefault { get; set; }
public virtual List<BidToSalesPeople> SalesPeople { get; set; }
public bool ProgramAdjustment { get; set; }
[Display(Name = "National/Local Programs")]
//[Required(ErrorMessage = "Nat Prg is required.")]
[Column(TypeName = "decimal(5,2)")]
public decimal? Programs { get; set; }
public string Notes_External { get; set; }
public string Notes_External_Footer { get; set; }
public virtual List<BidNotePricing> Notes_Pricing { get; set; }
public virtual List<BidNoteInternal> Notes_Internal { get; set; }
public virtual List<Bid_Item> Items { get; set; } //12/23/2021 SEO Refactor Bid Item Implementation - Changed from Collection To List
[Display(Name = "Bid Opened")]
[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime Date_BidOpened { get; set; }
[Display(Name = "Bid Accepted")]
[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime? Date_BidAccepted { get; set; }
[Display(Name = "Bid Expires")]
[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime? Date_BidExpires { get; set; }
[Display(Name = "Bid Pricing Start")]
[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime? Date_BidPriceStart { get; set; }
[Display(Name = "Bid Pricing End")]
[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime? Date_BidPriceEnd { get; set; }
[Display(Name = "Price Esc.")]
public string PriceEscalation { get; set; }
[Display(Name = "Is the Price Guaranteed?")]
[Required(ErrorMessage = "Price Guarantee is required.")]
public bool PriceGuarantee { get; set; }
[Display(Name = "Is this a Percentage Off?")]
[Required(ErrorMessage = "Is Percentage Off is required.")]
public bool IsPercentageOff { get; set; }
[Display(Name = "Percentage Off")]
[Required(ErrorMessage = "Specific Percentage Off is required.")]
[Column(TypeName = "decimal(5,2)")]
public decimal PercentageOff { get; set; }
[Display(Name = "Bid Active")]
[Required(ErrorMessage = "Is Bid Active required.")]
public bool Active { get; set; }
[Display(Name = "Quote?")]
public bool IsQuote { get; set; }
[Required(ErrorMessage = "Bid Status required.")]
public string Bid_StatusId { get; set; }
[Display(Name = "Bid Status")]
public virtual Bid_Status Bid_Status { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!IsQuote && Date_BidAccepted == null)
{
yield return new ValidationResult("You must have an Accepted Date before saving this record as a Bid", new string[] { "Date_BidAccepted" });
}
if (PriceGuarantee && Date_BidPriceEnd == null)
{
yield return new ValidationResult("You must have an End Date for Price Guaranteed bids/quotes", new string[] { "Date_BidPriceEnd" });
}
if (!Active && Date_BidExpires == null)
{
yield return new ValidationResult("You must have an Expire Date for Inactive bids/quotes", new string[] { "Date_BidExpires" });
}
}
//11/30/2021 SEO 681529
public virtual List<Bid_Location> Bid_Locations { get; set; }
//03/20/2022 SEO 681533
public virtual List<Bid_Distributor_Entity> Bid_Distributor_Entities { get; set; }
}
public class BidToSalesPeople : IEquatable<BidToSalesPeople>
{
[Key]
public string BidId { get; set; }
public virtual Bid Bid { get; set; }
[Key]
public string SalesPersonId { get; set; }
public virtual SalesPerson SalesPerson { get; set; }
public bool Equals(BidToSalesPeople other)
{
Contract.Requires(other != null);
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return this.BidId == other.BidId &&
this.SalesPersonId == other.SalesPersonId;
}
public override bool Equals(object obj)
{
return Equals(obj as BidToSalesPeople);
}
public override int GetHashCode()
{
return new Tuple<string, string>(SalesPersonId, BidId).GetHashCode();
}
}
}
Here is the RefreshScreen(null);
private void RefreshScreen(ModalResult modalResult)
{
if (modalResult is null || !modalResult.Cancelled)
{
this.StateHasChanged();
}
}
You question is a bit of a wall of code so I may have missed something important!
There's no such thing as null in html so:
<option value=null>Select a Product Line</option>
actually sets ProductLineId to "null" if selected, which is a valid value for the validator.
Here's some code that I use that "forces" a choice decision on Selects. It's standalone so you can copy and paste it into a page and see it in action.
Once you go to the dropdown you have to choose a value. If you exit without selecting by tabbing no value is set so it's still null and fails validation. Once a value is selected the "-- Select a Product Line --" option disappears.
#page "/"
<PageTitle>Index</PageTitle>
<EditForm Model=this.model>
<DataAnnotationsValidator />
<select class="form-select mb-2" value="#model.ProductLineId" #onchange=this.ProductLineChange>
#if (model.ProductLineId is null)
{
<option disabled selected value="">-- Select a Product Line --</option>
}
#foreach (ProductLine a in _productLines)
{
<option value="#a.Id">#a.Name</option>
}
</select>
<ValidationMessage For="() => this.model.ProductLineId" />
<button class="btn btn-success" type="submit">Submit</button>
</EditForm>
<div>
#model.ProductLineId
</div>
#code {
private Model model = new();
private async Task ProductLineChange(ChangeEventArgs e)
{
this.model.ProductLineId = e.Value?.ToString() ?? null;
// emulate some async work
await Task.Delay(200);
}
public class Model
{
[Required(ErrorMessage = "Product Line is required.")]
public string? ProductLineId { get; set; }
}
private List<ProductLine> _productLines = new()
{
new() { Name = "French" },
new() { Name = "English" },
new() { Name = "Spanish" },
new() { Name = "Swedish" },
};
public record ProductLine
{
public string Id { get; init; } = Guid.NewGuid().ToString();
public string Name { get; init; } = string.Empty;
}
}
You should be able to use this to resolve your problem.

The ViewData item that has the key "my ID" is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'

Trying to edit a foreign key value in a table. In the edit of my controller I create a viewbag item as a selectlist of the foreign table, with the selected value from the table I want to edit. I am able to populate the dropdownlistfor the correct field, and the correct value is selected. I added the id's to the edit(BIND"...") values, but when I pass the values, the modelstate is invalid.
The simplified Model:
public class NOEDetail
{
[Key]
public int noeKey { get; set; }
[Required]
public virtual Patient patientID { get; set; }
[Display(Name="Attending Physician")]
public virtual Physician attendingPhysician { get; set; }
[Display(Name="Certifying Physician")]
public virtual Physician certifyingPhysician { get; set; }
//public IEnumerable<Physician> attendingEnum { get; set; }
//public IEnumerable<Physician> certifyingEnum { get; set; }
[StringLength(60)]
[Display(Name = "Last Name")]
public string lastName { get; set; }
[StringLength(35)]
[Display(Name = "First Name")]
public string firstName { get; set; }
[StringLength(25)]
public string middleName { get; set; }
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
[Display(Name = "Date Of Birth")]
public DateTime dob { get; set; }
[Display(Name = "Gender")]
public char? gender { get; set; }
[Display(Name = "Address 1")]
[StringLength(50)]
public string addr1 { get; set; }
[Display(Name = "Address 2")]
[StringLength(50)]
public string addr2 { get; set; }
[StringLength(50)]
[Display(Name = "City")]
public string city { get; set; }
[StringLength(2)]
[Display(Name = "State")]
public string state { get; set; }
[StringLength(9)]
[Display(Name = "Zip")]
public string zip { get; set; }
}
The simplified controller:
public class NOEDetailsController : Controller
{
private revDemo db = new revDemo();
// GET: NOEDetails/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
NOEDetail nOEDetail = db.NOEDetails.Find(id);
if (nOEDetail == null)
{
return HttpNotFound();
}
ViewBag.attendingPhysicianSelectList = new SelectList(db.Physician, "physicianID", "Fullname", nOEDetail.attendingPhysician.physicianID);
ViewBag.certifyingPhysicianSelectList = new SelectList(db.Physician, "physicianID", "Fullname", nOEDetail.certifyingPhysician.physicianID);
return View(nOEDetail);
}[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "noeKey,lastName,firstName,middleName,addr1,addr2,city,state,zip attendingPhysician,certifyingPhysician")] NOEDetail nOEDetail)
{//^^ here I added the attendingPhysician, and certifyingPhysician code BY HAND to get rid of the first error, but then the model was incorrect.
//ViewBag.attendingPhysicianSelectList = new SelectList(db.Physician, "physicianID", "Fullname", nOEDetail.attendingPhysician.physicianID);
//ViewBag.certifyingPhysicianSelectList = new SelectList(db.Physician, "physicianID", "Fullname", nOEDetail.certifyingPhysician.physicianID);
if (ModelState.IsValid)
{
db.Entry(nOEDetail).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(nOEDetail);
}
The View Item:
#Html.DropDownListFor(m => m.attendingPhysician.physicianID, ViewBag.attendingPhysicianSelectList as SelectList,null, new { #class = "form-control"})
The issue is when I submit the data. The data is retrieved correctly but is being sent back to the controller as a selectlistitem instead of the value tied to the item, which is what I want. Help, please?

C# Using If Statements with enum

I want a different viewbag message displayed depending on which option is chosen from a dropdownlist of Enumerators however I'm not sure how to do this. Im using a viewmodel and passing the data through the controller, here is the ViewModel and class, an explanation on how to use if statements with ViewModels/Enumerators would be highly beneficial. I have tried assigning variables but Im realizing that all im doing is saying THIS is THIS, so thats not going to get the data from the Orders Postage enum. Any help and explanations appreciated, still learning.
ViewModel;
{
public class MyOrdersViewModel
{
public int OrderId { get; set; }
public System.DateTime OrderDate { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
public decimal Total { get; set; }
public bool HasBeenShipped { get; set; }
public Postage? PostageList { get; set; }
public List<MyOrderDetails> Details { get; set; }
}
public class MyOrderDetails
{
public string Title { get; set; }
public string Colour { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
}
}
Controller;
public ActionResult Index(Order order)
{
string currentUser = this.User.Identity.GetUserName();
List<T_shirt_Company_v3.ViewModels.MyOrdersViewModel> list = (from o in new TshirtStoreDB().Orders
.Where(o => o.Username == currentUser)
.OrderByDescending(o => o.OrderDate)
.Select(o => new MyOrdersViewModel()
{
OrderId = o.OrderId,
Address = o.Address,
FirstName = o.FirstName,
LastName = o.LastName,
City = o.City,
OrderDate = o.OrderDate,
PostalCode = o.PostalCode,
Total = o.Total,
HasBeenShipped = o.HasBeenShipped,
PostageList = o.PostageList,
Details = (from d in o.OrderDetails
select new MyOrderDetails
{
Colour = d.Product.Colour,
Quantity = d.Quantity,
Title = d.Product.Title,
UnitPrice = d.UnitPrice
}).ToList()
}).ToList()
select o).ToList();
//#ViewBag.PostageStatus
//ViewBag.ShippedMessage = list.Where(w => w.HasBeenShipped).Any() ? "Order has been shipped" : "Order is being processed";
Postage value = Postage.FirstClass;
Postage value2 = Postage.StandardDelivery;
Postage value3 = Postage.TwentyFourHour;
if (value == Postage.FirstClass)
{
ViewBag.PostageStatus = ("First Class");
}
else
{
ViewBag.PostageStatus = (" Error ");
}
if (value2 == Postage.StandardDelivery)
{
ViewBag.PostageStatus = ("Standard Delivery");
}
if (value3 == Postage.StandardDelivery)
{
ViewBag.PostageStatus = ("24 hour delivery");
}
return View(list);
}
Order Class
namespace T_shirt_Company_v3.Models
{
//[Bind(Exclude = "OrderId")]
public partial class Order
{
[ScaffoldColumn(false)]
public int OrderId { get; set; }
[ScaffoldColumn(false)]
public System.DateTime OrderDate { get; set; }
[ScaffoldColumn(false)]
[Remote("CheckUserName", "Account")]
public string Username { get; set; }
[Required]
[StringLength(16, ErrorMessage = "Your name is too long")]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Your last name is required.")]
[StringLength(16, ErrorMessage = "Last name is too long.")]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required(ErrorMessage = "Address is required.")]
public string Address { get; set; }
[Required(ErrorMessage = "City is required.")]
public string City { get; set; }
[Required(ErrorMessage = "Postcode is required.")]
[Display(Name = "Post Code")]
public string PostalCode { get; set; }
[Required(ErrorMessage = "Country is required.")]
public string Country { get; set; }
[Required(ErrorMessage = "Phone number is required.")]
public string Phone { get; set; }
[RegularExpression(#"[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage = "Email doesn't look like a valid email address.")]
public string Email { get; set; }
[System.ComponentModel.DataAnnotations.Compare("Email")]
[Display(Name = "Confirm your email address")]
public string EmailConfirm { get; set; }
[ScaffoldColumn(false)]
public string PaymentTransactionId { get; set; }
[ScaffoldColumn(false)]
public bool HasBeenShipped { get; set; }
[ScaffoldColumn(false)]
//[ReadOnly(true)]
public decimal Total { get; set; }
[Required]
[Range(0, 2, ErrorMessage = "Select a delivery method")]
public Postage? PostageList { get; set; }
public CardDetails cardDetails { get; set; }
//public List<CardDetails> cardDetails { get; set; }
public List<OrderDetail> OrderDetails { get; set; }
}
public enum Postage {[Display(Name = "Standard Delivery - Free")]StandardDelivery, [Display(Name = "First Class Delivery - £4.99")]FirstClass, [Display(Name = "24 Hour Delivery - £9.99")]TwentyFourHour }
}
Why not simply use a switch statement on the enum? Perhaps the misunderstanding was that the type was nullable. With nullables you can invoke .GetValueOrDefault and then switch on the return for the enum value.
switch (order.Postage.GetValueOrDefault())
{
case Postage.StandardDelivery:
ViewBag.PostageStatus = "Standard Delivery";
break;
case Postage.FirstClass:
ViewBag.PostageStatus = "First Class";
break;
case Postage.TwentyFourHour:
ViewBag.PostageStatus = "24 hour delivery";
break;
default:
ViewBag.PostageStatus = "Error";
break;
}
This prevents the usage of the if statement and simplifies the readability for the user.

How to set the Default value for DropDown when post back in MVC3

I am working with MVC3 and I have a dropdown that I need to set the default value from the database.
When I select a value in the dropdownlist I get a postback and the value I selected is selected even after the postback. How do I get the default value, <--Select Project--> as selected value again after the postback? How is this done in MVC?
Below are the Controller and Views that I use.
My Models
namespace BugTracker.Models
{
public class BugModel
{
public List<BugModel> InsertBug {get; set;}
public List<BugModel> Bugs { get; set; }
public Int16 BugID { get; set; }
[Required(ErrorMessage = "Title is required")]
public string Title { get; set; }
[Required(ErrorMessage = "Description is required")]
public string Description {get; set;}
[Required(ErrorMessage = "Version is required")]
public string Version { get; set; }
[Required(ErrorMessage = "BuildNumber is required")]
public string BuildNumber { get; set; }
[Required(ErrorMessage = "CreatedDate is required")]
public string CreatedDate { get; set; }
[Required(ErrorMessage = "GetDate is required")]
public string GetDate { get; set; }
public List<BugModel> GetProjects { get; set; }
public int ProjectID { get; set; }
[Required(ErrorMessage = "ProjectName is required")]
public string ProjectName { get; set; }
public List<BugModel> GetEmployee {get; set;}
public int EmployeeID { get; set; }
public int CreatedByID { get; set; }
[Required(ErrorMessage = "EmployeeName is required")]
public string EmployeeName {get;set;}
[Required(ErrorMessage = "CreatedBy is required")]
public string CreatedBy { get; set; }
public List<BugModel> GetCategory { get; set;}
public int CategoryID { get; set; }
[Required(ErrorMessage = "Category is required")]
public string Category { get; set;}
public List<BugModel> GetSeverity { get; set;}
public int SeverityID { get; set; }
[Required(ErrorMessage = "Severity is required")]
public string Severity { get; set; }
public List<BugModel> GetPriority { get; set; }
public int PriorityID { get; set; }
[Required(ErrorMessage = "Prirority is required")]
public string Prirority { get; set;}
public List<BugModel> GetReleasePhase { get; set;}
public int ReleasePhaseID { get; set; }
[Required(ErrorMessage = "ReleasePhase is required")]
public string ReleasePhase { get; set;}
public List<BugModel> GetTypes { get; set; }
public int TypeID { get; set; }
[Required(ErrorMessage = "Type is required")]
public string Type { get; set; }
public List<BugModel> GetBugHistory { get; set; }
[Required(ErrorMessage = "AssignTo is required")]
public string AssignTo { get; set; }
}
}
My controllers are
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult BugDetails(FormCollection form,string Projects,string Prirority,string CreatedBy,BugModel model)
{
var modelList = new List();
ViewBag.Projects = new SelectList(GetProjects(), "ProjectId", "ProjectName");
ViewBag.Prirority = new SelectList(GetPriority(), "PriorityID", "Prirority");
ViewBag.CreatedBy = new SelectList(GetEmployee(), "EmployeeID", "EmployeeName");
using (SqlConnection conn = new SqlConnection(#"Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=BugtrackerNew;Data Source=SSDEV5-HP\SQLEXPRESS"))
{
SqlCommand dCmd = new SqlCommand("Filter", conn);
dCmd.CommandType = CommandType.StoredProcedure;
conn.Open();
dCmd.Parameters.Add(new SqlParameter("#ProjectID", Projects));
dCmd.Parameters.Add(new SqlParameter("#PriorityID",Prirority));
dCmd.Parameters.Add(new SqlParameter("#CreatedByID",CreatedBy));
SqlDataAdapter da = new SqlDataAdapter(dCmd);
DataSet ds = new DataSet();
da.Fill(ds);
for (int i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
{
model.BugID = Convert.ToInt16(ds.Tables[0].Rows[i]["BugID"]);
model.Title = ds.Tables[0].Rows[i]["Title"].ToString();
model.Description = ds.Tables[0].Rows[i]["Description"].ToString();
conn.Close();
return View(modelList);
}
}
My view page is
using (Html.BeginForm())
{ %>
<%: Html.DropDownList("Projects", (SelectList)ViewBag.Projects)%>
<%: Html.DropDownList("Prirority", (SelectList)ViewBag.Prirority, "Select Project")%>
<%: Html.DropDownList("CreatedBy", (SelectList)ViewBag.CreatedBy, "--Select Project--")%>
}
When the page returns from postback, I would like the default value to be selected, but in MVC there is no page load method. So, please could somebody point me in the right direction.
Thank you in advance.
By using DropDownListFor(), you could pass the wanted project into your model on your view.
Example:
#{ var projects= (IEnumerable<Projects>)ViewBag.Projects; }
#Html.DropDownListFor(m => m.ProjectId, projects, string.Empty)
In short, use your model to determine the selected value in a dropdownlist, provide the possible value through your viewbag.
If your property on your model is the default value of the property type, the dropdownlistfor will show the first value of the list with possible values.

Database Calculations - MVC 3 and CodeFirst

I'm trying to write a method that generates multiple commission slips. This is for a college, where clients are enrolled with tutors in a class called Enrollments. With this method, I am trying to accumulate the monthly fee of the tutors' clients multiplied by their commission percentages, as tutors earn a certain commission on the lessons they give. Here is my code for this:
public ActionResult CreateBulkCommissions()
{
var month = DateTime.Now.ToString("MMMM");
var enrolments = db.Enrollments.ToList();
var newCommissions = from enrolment in enrolments
select new TutorCommission()
{
CommissionAmount = enrolment.MonthlyFee,
CommissionMonth = month, // string constant
CommissionStatus = "Unpaid",
Tutor = enrolment.Tutor
};
foreach (var newCommission in newCommissions)
{
List<TutorCommission> TutorComs = newCommissions.GroupBy(g => g.Tutor).Select(s => new TutorCommission
{
CommissionAmount = s.Sum(u => u.CommissionAmount) * s.Key.TutorCommissionPercentage,
TutorNoID = s.Key.TutorNoID
}).ToList();
db.TutorCommission.Add(newCommission);
db.SaveChanges();
}
return RedirectToAction("Index");
}
The problem is that TutorCommission entries are created for each individual enrollment, instead of one entry per tutor (for the month) with the total commission amount. I.e. Ashley has 3 clients and therefore 3 enrollments and currently 3 TutorCommission entries are being created for him. I want to add up the enrollments amounts for one entry. In addition, the amount is not being multiplied by the commission percentage, so it is just saving as the full enrollment monthly fee. Relevant classes are:
public class Enrollment
{
[Key]
[Display(Name = "Enrollment ID Number")]
public long EnrollmentIDNumber { get; set; }
[Display(Name = "Client ID Number")]
public long ClientNumberID { get; set; }
[Display(Name = "Tutor ID Number")]
public long TutorNoID { get; set; }
[Display(Name = "Course Name")]
public string CourseName { get; set; }
[Display(Name = "Lesson Time")]
public string LessonTime { get; set; }
[Display(Name = "Lesson Day")]
public string LessonDay { get; set; }
[Display(Name = "Lesson Location")]
public string LessonLocation { get; set; }
[Display(Name = "Lesson Type")]
public string LessonType { get; set; }
[Display(Name = "Lesson Level")]
public string LessonLevel { get; set; }
[Display(Name = "Monthly Fee")]
public long MonthlyFee { get; set; }
public virtual Client Client { get; set; }
public virtual Tutor Tutor { get; set; }
}
public class TutorCommission
{
[Key]
[Display(Name = "Commission ID")]
public long CommissionID { get; set; }
[Display(Name = "Commission Month")]
public string CommissionMonth {get; set;}
[Display(Name = "Commission Amount")]
public double CommissionAmount { get; set; }
[Display(Name = "Commission Status")]
public string CommissionStatus { get; set; }
[Display(Name = "Tutor ID Number")]
public long TutorNoID { get; set; }
public virtual Tutor Tutor { get; set; }
public virtual ICollection<CommissionPayments> CommissionPayments { get; set; }
}
public class Tutor
{
[Key]
[Display(Name = "Tutor ID Number")]
public long TutorNoID { get; set; }
[Required]
[StringLength(50, ErrorMessage="First name must be less than 50 characters")]
[Display(Name = "First Name")]
public string TutorFirstName { get; set; }
[StringLength(50, ErrorMessage = "Last name must be less than 50 characters")]
[Display(Name = "Last Name")]
public string TutorLastName { get; set; }
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
[Display(Name = "Birth Date")]
public DateTime? TutorBirthDate { get; set; }
[Display(Name = "Cellphone Number")]
public string TutorCellphoneNumber { get; set; }
[Display(Name = "Home Number")]
public string TutorHomeNumber { get; set; }
[RegularExpression("^[a-z0-9_\\+-]+(\\.[a-z0-9_\\+-]+)*#[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2,4})$", ErrorMessage = "Not a valid email address")]
[Display(Name = "Email Address")]
public string TutorEmailAddress { get; set; }
[Display(Name = "Street Address")]
public string TutorStreetAddress { get; set; }
[Display(Name = "Suburb")]
public string TutorSuburb { get; set; }
[Display(Name = "City")]
public string TutorCity { get; set; }
[Display(Name = "Postal Code")]
public string TutorPostalCode { get; set; }
[Display(Name="Full Name")]
public string FullName
{
get
{
return TutorFirstName + " " + TutorLastName;
}
}
[Display(Name="Commission Percentage")]
[Required]
public double TutorCommissionPercentage { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
public virtual ICollection<TutorCommission> TutorCommissions { get; set; }
}
Thanks,
Amy
You can try moving the grouping logic outside the foreach loop, then iterating on the grouped list. So instead of
foreach (var newCommission in newCommissions)
{
List<TutorCommission> TutorComs = newCommissions.GroupBy(g => g.Tutor).Select(s => new TutorCommission
{
CommissionAmount = s.Sum(u => u.CommissionAmount) * s.Key.TutorCommissionPercentage,
TutorNoID = s.Key.TutorNoID
}).ToList();
db.TutorCommission.Add(newCommission);
db.SaveChanges();
}
try
List<TutorCommission> TutorComs = newCommissions.GroupBy(g => g.Tutor).Select(s => new TutorCommission
{
CommissionAmount = s.Sum(u => u.CommissionAmount) * s.Key.TutorCommissionPercentage,
TutorNoID = s.Key.TutorNoID
}).ToList();
foreach (var tutorCom in TutorComs)
{
db.TutorCommission.Add(tutorCom);
db.SaveChanges();
}
See if that is closer to the desired result.

Categories