ASP.NET MVC C# set model property values - c#

I am having some problems with setting the values for my summaryVm in the controller method. I am accepting an OrderVM and I have checked in debug mode and the properties of OrderVM are all set when it is passed and the Order also had all values set (including orderID). However later in the method when I try to set the values of my SummaryVm to these values the summaryVm.Tickets is null, as is the summaryVm.orderID. Yet email and eventID are being set fine.
If anyone has suggestions on what I'm doing wrong it would be great because I'm at a loss to see what's wrong.
[HttpPost]
public ActionResult Create(OrderVM model)
{
if (!ModelState.IsValid)
return View("CreateOrder", model);
}
string currentUserId = User.Identity.GetUserId();
ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);
Event currentEvent = db.Events.Find(model.EventID);
Order order = new Order
{
OrderDate = DateTime.Now,
EventID = model.EventID,
Event = currentEvent,
user = currentUser
};
float total = 0;
// Initialise a TicketsOrdered data model for each valid ticket
foreach (TicketVm ticket in model.Tickets.Where(t => t.Quantity > 0))
{
total += (ticket.Price*ticket.Quantity);
TicketsOrdered ticketOrder = new TicketsOrdered
{
OrderID = order.OrderID,
TicketID = ticket.TicketID,
Quantity = ticket.Quantity
};
db.ticketsOrdered.Add(ticketOrder);
}
order.OrderTotal = total;
currentEvent.Order.Add(order);
currentUser.Order.Add(order);
SummaryVm summaryVm = new SummaryVm
{
email = order.user.UserName,
orderID = order.OrderID,
tickets = model.Tickets,
totalPrice = total,
eventID=model.EventID,
stripePublishableKey=ConfigurationManager.AppSettings["stripePublishableKey"]
};
db.Orders.Add(order);
db.SaveChanges();
return RedirectToAction("OrderSummary", "Order", summaryVm);
}
public class OrderVM
{
public int ID { get; set; }
public int EventID { get; set; }
public string EventName { get; set; }
// additional properties of Event you want to display
public DateTime OrderDate { get; set; }
public string FirstName { get; set; }
// additional properties of Order and OrderDetails you want to edit
public IList<TicketVm> Tickets { get; set; }
public Event events {get; set;}
}
public class SummaryVm
{
public IList<TicketVm> tickets { get; set; }
public string email { get; set; }
public float totalPrice { get; set; }
public int orderID { get; set; }
public int eventID { get; set; }
public string stripePublishableKey { get; set; }
public string StripeToken { get; set; }
public string StripeEmail {get;set;}
}

Move SaveChanges before creating SummaryVm
...
db.Orders.Add(order);
db.SaveChanges();
SummaryVm summaryVm = new SummaryVm
{
email = order.user.UserName,
orderID = order.OrderID,
tickets = model.Tickets,
totalPrice = total,
eventID=model.EventID,
stripePublishableKey=ConfigurationManager.AppSettings["stripePublishableKey"]
};
return RedirectToAction("OrderSummary", "Order", summaryVm);
and it will work.

Related

How to get data get from multiple tables and update using EF

I have successfully inserted data into two tables which are working fine. Now I am just stuck as to how I can get the details from both tables and update them. After inserting, I want to query both tables using an id and get the records, and then use the Id to update.
This is what I am looking for.
get data from two tables
update tables(pass id)
It must be an API that communicates with my classes because I want to display the data from the view
DB Models
1.
public class WholesaleRateSheetMarkup
{
[Key]
public int RateSheetMarkupId { get; set; }
[Required]
public int ResellerId { get; set; }
[StringLength(50)]
public string RatesheetName { get; set; }
}
2.
public class WholesaleRateSheet
{
[Key]
public int RateSheetId { get; set; }
[Required]
public int RateSheetMarkupId { get; set; }
public string CountryCode { get; set; }
public string Description { get; set; }
public decimal Peak { get; set; }
public bool IsSouthAfricanRate { get; set; }
public bool IsInertnationRate { get; set; }
public bool IsSpecificRate { get; set; }
public int DestinationGroupSetId { get; set; }
public int DestinationGroupId { get; set; }
public string DestinationLookup { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedByUsername { get; set; }
public DateTime LastUpdatedDate { get; set; }
public string UpdatedByUsername { get; set; }
}
My controller: This controller calls service class
[HttpPost]
[Route("[controller]/addRateSheet/{resellerId}/{productName}")]
public IActionResult AddRateSheet(int resellerId, string productName , int destinationGroupSetId, [FromBody]List<RateSheetSummary> rateSheetSummaries)
{
RateSheetService rateSheetService = new RateSheetService();
return Ok(rateSheetService.SaveRateSheet(resellerId, productName, rateSheetSummaries));
}
This is how I am saving to the database
public RateSheetModel SaveRateSheet(int resellerId, string productName, [FromBody]List<RateSheetSummary> rateSheetSummaries)
{
int latestId;
RateSheetModel rateSheetModel = new RateSheetModel();
try
{
#region Save rate sheet to the tabase
if (RateSheetObj != null)
{
#region WholesaleRateSheetMarkup
var wholesaleRateSheetMarkup = new WholesaleRateSheetMarkup
{
ResellerId = resellerId,
RatesheetName = productName,
};
_Context.WholesaleRateSheetMarkup.Add(wholesaleRateSheetMarkup);
_Context.SaveChanges();
//get latest RateSheetMarkupId
latestId = wholesaleRateSheetMarkup.RateSheetMarkupId;
#endregion
#region WholesaleRateSheet
#region commented out
List<WholesaleRateSheet> wholesaleRateSheets = new List<WholesaleRateSheet>();
foreach (var item in rateSheetSummaries)
{
wholesaleRateSheets.Add(new WholesaleRateSheet()
{
RateSheetMarkupId = latestId,
CountryCode = item.CountryCode,
Description = item.Description,
Peak = item.Peak,
IsSouthAfricanRate = item.IsSouthAfricanRate,
IsSpecificRate = item.IsSpecificRate,
DestinationGroupSetId = 1,
DestinationGroupId = 1,
DestinationLookup = item.DestinationLookup,
CreatedDate = DateTime.Now
}); ;
_Context.WholesaleRateSheet.AddRange(wholesaleRateSheets);
_Context.SaveChanges();
}
#endregion
}
}
}
}
Trying to fetch data from my tables. At this point, I don't know how to continue further as I want to get the details and so that I can bind the data from the view.
public RateSheetModel getRatesheetDetails(int rateSheetMarkupId)
{
RateSheetModel model = new RateSheetModel();
using (var context = new AppClientZoneContext())
{
var select = (from rsm in context.WholesaleRateSheetMarkup
join rs in context.WholesaleRateSheet
on rsm.RateSheetMarkupId equals rs.RateSheetMarkupId
where rsm.RateSheetMarkupId == rateSheetMarkupId
select new
{
rsm.RatesheetName,
rs.CountryCode,
rs.Description,
rs.Peak,
rs.IsSouthAfricanRate,
rs.IsInertnationRate,
rs.RateSheetMarkupId,
rs.IsSpecificRate,
rs.DestinationGroupSetId,
rs.DestinationGroupId,
rs.DestinationLookup,
rs.CreatedDate,
rs.CreatedByUsername,
rs.LastUpdatedDate,
rs.UpdatedByUsername,
}).FirstOrDefault();
}
return model;
}
Update API
[HttpPost]
[Route("[controller]/updateRateSheet/{resellerId}/{ratesheetId}")]
public IActionResult UpdateRateSheet(int resellerId, int ratesheetId, string productName)
{
RateSheetService UpdateRateSheetService = new RateSheetService();
return Ok(UpdateRateSheetService.UpdateRateSheet(resellerId,ratesheetId, productName));
}
Update function: I don't know how to best approach update functionality
public RateSheetModel UpdateRateSheet(int resellerId, int rateSheetId, string productName)
{
RateSheetModel mm = new RateSheetModel();
return mm;
}

how i update multiple table using viewmodel in Asp.net mvc

Employee Model
public class Employee
{
[Key]
public int EmployeeID { get; set; }
public string Name { get; set; }
public virtual Department Departments { get; set; }
public int DepartmentID { get; set; }
}
Department Model
public class Department
{
public int DepartmentID { get; set; }
public string DepartmentName { get; set; }
}
View Model for Department and Employee
public class EDViewModel
{
public int ID { get; set; }
public int EmployeeID { get; set; }
public string Name { get; set; }
public Department Departments { get; set; }
public int DepartmentID { get; set; }
public string DepartmentName { get; set; }
}
Now i want to update both tables with single view.
Controller
public ActionResult Edit(int?id)
{
// write some code for update both table at once time
}
PostMethod
[HttpPost]
public ActionResult Edit(EDViewModel Emodel)
{
var user = db.Employees.Where(c => c.Employee_Id == Emodel.Employee_Id).FirstOrDefault();
user.UserName = Emodel.UserName;
user.ProfilePicture = Emodel.ProfilePicture;
db.Entry(user).State = EntityState.Modified;
db.Entry(user).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Home");
}
But in this method only Update Employee record not department
After many searching finally i get a solid solution
hope you like or improve this.
Controller
public ActionResult Edit(int? id)
{
MYDb db = new MYDb();
var user = db.Employees.Where(c => c.Employee_Id == Emodel.Employee_Id).FirstOrDefault();
if (user != null)
{
var vm = new EDViewModel { Employee_id = user.Employee_id, departmentName = user.departmentName };
if (user.department != null)
{
user.Departmet_id = vm.Departments.Departmet_id;
user.DepartmentName = vm.Departments.DepartmentName;
user.Employee_id = vm.employee_id;
user.employeeName = vm.employeeName;
}
return View(user);
}
return Content("Invalid Id");
}
[HttpPost]
public ActionResult Edit(EDViewModel Emodel)
{
var user = db.Employees.Where(c => c.Employee_Id == Emodel.Employee_Id).FirstOrDefault();
user.EmployeeId = Emodel.EmployeeId;
user.EmployeeName= Emodel.EmployeeName;
user.DepartmentName= Emodel.Departmt.DepartmentName;
// Just remove this line
// db.Entry(user).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Home");
}
it worked for me
just remove this
db.Entry(user).State = EntityState.Modified;
if we not remove this entityvalidation occur

how to manipulate a list of properties in a class when sending one email?

I'm trying to implement order confirmation in application (MVC 4) which uses a shopping cart.
I'm at the stage where I want to send out an email to both the customer and Admin user to confirm the order.
I want to send one email for one order(Cart).
My Cart class.
I have a Cart Model:
namespace MerchandiseProject.Domain.Entities
{
public class Cart
{
private List<CartLine> lineCollection = new List<CartLine>();
public void AddItem(Product product, int quantity)
{
CartLine line = lineCollection
.Where(p => p.Product.ProductID == product.ProductID)
.FirstOrDefault();
if (line == null)
{
lineCollection.Add(new CartLine { Product = product,
Quantity = quantity });
}
else
{
line.Quantity += quantity;
}
}
public void RemoveLine(Product product)
{
lineCollection.RemoveAll(l => l.Product.ProductID == product.ProductID);
}
public decimal ComputeTotalValue()
{
return lineCollection.Sum(e => e.Product.Price * e.Quantity);
}
public void Clear()
{
lineCollection.Clear();
}
public IEnumerable<CartLine> Lines
{
get { return lineCollection; }
}
}
public class CartLine
{
public Product Product { get; set; }
public int Quantity { get; set; }
}
}
I am passing this model and the shipping details model back to POST checkout actionResult in my Cartcontroller and assigning their values to an Orders class, these details are also persisted to the database.
The information being past back to the database are correct.
But how to extract it in the likes of a "foreach" statement has me stuck !
Orders Class:
namespace MerchandiseProject.Domain.Entities
{
public class Orders
{
private List<OrderLine> lineCollection = new List<OrderLine>();
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int OrderId { get; set; }
public DateTime OrderDate { get; set; }
public int ProductID { get; set; }
public string ProductName { get; set; }
public decimal ProductUnitPrice { get; set; }
public int Quantity { get; set; }
public decimal OrderTotal { get; set; }
public string Name { get; set; }
public string UserName { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public string Country { get; set; }
public bool GiftWrap { get; set; }
public IEnumerable<OrderLine> Lines
{
get { return lineCollection; }
}
}
public class OrderLine
{
public Product Product { get; set; }
public int Quantity { get; set; }
}
}
My problem is in my Cart Controller Checkout ViewResult [POST], an email goes out for every type of product in the cart, I want to send one e-mail with the list of products ordered ? make sense ?
Cart Controller:
[HttpPost]
public ViewResult Checkout(Cart cart, ShippingDetails shippingDetails)
{
var CurrentUser = HttpContext.User;
string currentUserName = CurrentUser.Identity.Name;
if (cart.Lines.Count() == 0)
{
ModelState.AddModelError("", "Sorry, your cart is empty!");
}
if (ModelState.IsValid)
{
foreach (var line in cart.Lines)
{
var model = new Orders()
{
ProductName = line.Product.Name,
ProductUnitPrice = line.Product.Price,
Quantity = line.Quantity,
OrderTotal = line.Quantity * line.Product.Price,
UserName = currentUserName,
Name = shippingDetails.Name,
Line1 = shippingDetails.Line1,
Line2 = shippingDetails.Line2,
Line3 = shippingDetails.Line3,
City = shippingDetails.City,
State = shippingDetails.State,
Country = shippingDetails.Country,
GiftWrap = shippingDetails.GiftWrap,
OrderDate = DateTime.Now,
Zip = shippingDetails.Zip,
};
new MailController(_actionMailer).OrderDetailsEmail(model).Deliver();
}
orderProcessor.SaveOrder(currentUserName ,cart, shippingDetails);
cart.Clear();
return View("Completed");
}
else
{
return View(shippingDetails);
}
}
Please note - asp.net MVC 4 using razor views.
As #DStanley said, you are literally saying to send an email for each line item by having your MailController line within the foreach loop. If the problem is you need access to model outside the context of the foreach loop, then you need to persist it in a variable in a parent scope. For example:
var lineItems = new List<Order>();
foreach (var line in cart.Lines)
{
lineItems.Add(new Order
{
...
});
}
However, if you're going to do that, it's more efficient to just use Select:
var lineItems = cart.Lines.Select(m => new Order
{
ProductName = m.Product.Name,
...
});
Removing the need for the foreach completely.

Update Parent and Insert Child Telerik Opn Access with AutoMapper

I am using Telerik Open Access for database operation. I have a Parent Class named Order and it includes 2 classes named OrderHistory and Tasks. Now any kind of event happen like if order is put on hold or put for dispatching it's related entry will be put on OrderHistory table and Order table will be updated. Now I have done following code but it works sometimes but sometimes not. I don't know much about this telerik open access and automapper.
controller call:
OrderDTO updateorder = orderManagement.GetOrdersByOrderId(2);
updateorder.QueueId = 3;
updateorder.IsLocked = false;
updateorder.UpdatedBy = Convert.ToInt32(Session["UserId"], CultureInfo.CurrentCulture);
updateorder.UpdatedDate = DateTime.Now;
OrderHistoryDTO alertDto = new OrderHistoryDTO()
{
Event = 'Putting On Hold',
OrderID = orderDTO.Id
UserID = Convert.ToInt32(Session["UserId"], CultureInfo.CurrentCulture),
OccuerdDate = DateTime.Now,
EventType = 'Event'
};
updateorder.OrderHistories.Clear();
updateorder.OrderHistories.Add(alertDto);
updateorder = orderManagement.UpdateOrder(updateorder);
db operations
public OrderDTO UpdateOrder(OrderDTO orderEntity)
{
AutoMapper.Mapper.CreateMap<OrderDTO, Order>()
.ForMember(d => d.Tasks, m => m.Ignore())
.ForMember(d => d.OrderHistories, m => m.MapFrom(s => s.OrderHistories));
AutoMapper.Mapper.CreateMap<OrderHistoryDTO, OrderHistory>();
var orderBase = AutoMapper.Mapper.Map<Order>(orderEntity); // It will sometimes make OrderHistories list count to 0. though in starting orderEntity has OrderHistories count = 1.
base.Update(orderBase);
base.Save();
orderEntity = AutoMapper.Mapper.Map<OrderDTO>(orderBase);
return orderEntity;
}
OrderDTO
public class OrderDTO
{
public int OrderID { get; set; }
public bool? IsLocked { get; set; }
public int QueueId { get; set; }
[ScriptIgnore]
private IList<OrderHistoryDTO> _orderHistories = new List<OrderHistoryDTO>();
[ScriptIgnore]
public virtual IList<OrderHistoryDTO> OrderHistories
{
get { return this._orderHistories; }
}
public DateTime? UpdatedDate { get; set; }
public int? UpdatedBy { get; set; }
}
OrderHistoryDTO
public class OrderHistoryDTO
{
public int ID { get; set; }
public int UserID { get; set; }
public int OrderID { get; set; }
public string Event { get; set; }
public string EventType { get; set; }
public DateTime? OccuerdDate { get; set; }
public UserDTO User { get; set; }
}

Asp.Net MVC 4 Controller to update database

I have the following code:
Model
public class Orders
{
public int Id { get; set; }
public int UserId { get; set; }
public int ProductId { get; set; }
public int Quantity { get; set; }
public double Price { get; set; }
public bool OrderStatus { get; set; }
public string OrderNumber { get; set; }
public string AdminStatus { get; set; }
public bool PaymentStatus { get; set; }
public DateTime OrderDate { get; set; }
}
Controller
public ActionResult CheckOut()
{
if (Request.IsAjaxRequest())
{
var userid = WebSecurity.CurrentUserId;
var data = _bbdb.Orders.Where(x => x.OrderStatus == false && x.UserId == userid).ToList();
foreach (var item in data)
{
_bbdb.Orders.Add(new Orders
{
Id = item.Id,
UserId = item.UserId,
ProductId = item.ProductId,
Quantity = item.Quantity,
Price = item.Price,
OrderStatus = true,
OrderNumber = item.UserId + DateTime.Now.ToShortTimeString(),
AdminStatus = item.AdminStatus,
PaymentStatus = item.PaymentStatus,
OrderDate = DateTime.Today
});
_bbdb.SaveChanges();
}
}
var cartdata = GetCartItems();
return PartialView("_CartTable", cartdata);
}
How can I change this bit code _bbdb.Orders.Add(new Orders to UPDATE instead ADD.
I thought something like _bbdb.Orders.AddOrUpdate(new Orders would do the trick, but I does not exist.
It is adding the right value, but I want to update the records not add new ones.
Any suggestion on how to improve or change will be appreciated.
Not sure how correct I am here, but try this...
_bbdb tracks the changes, so you simply need to get the item from the db, make the changes you need and then save them.
foreach (var item in data)
{
item.Price = 100; //Set whatever values you need to update
}
_bbdb.SaveChanges();
Also, notice that the SaveChanges() method was moved outside of foreach. The context will track the changes so you don't need to call SaveChanges after each item is added.
Finally, I believe that you don't need ToList() after the Where-clause

Categories

Resources