Edit & Delete object with ViewModel - asp.net-mvc

I've successfully implemented a viewmodel so I can create and return items from my database using two tables. My issue is editing and deleting individual items.
I was able to edit/delete when I was using just one table, but with two, i've run into a snag.
My view uses a viewmodel now. I am not able to figure out how to pass the specific object id when Passing an id and TransactionViewModel Viewmodel into my Edit method Parameters.
Here is my old Edit and Edit post.
public ActionResult Edit(int id = 0)
{
Transactions transactions = _db.Transactions.Find(id);
if (transactions == null)
{
return HttpNotFound();
}
return View(transactions);
}
[HttpPost]
//[ValidateAntiForgeryToken]
public ActionResult Edit(TransactionViewModel viewModel)
{
var transactionType = viewModel.Transaction.TransactionType;
if (ModelState.IsValid)
{
//If the transaction category is an Expense, set it to a negative so we can calculate later.
if (transactionType == Classes.Constants.Expense || (transactionType == Classes.Constants.Payment && viewModel.Transaction.Amount < 0))
{
viewModel.Transaction.Amount *= -1;
}
var transaction = new Transactions()
{
ClientId = viewModel.Transaction.ClientId,
Amount = viewModel.Transaction.Amount,
Date = viewModel.Transaction.Date,
Category = viewModel.Transaction.Category,
Description = viewModel.Transaction.Description,
TransactionType = viewModel.Transaction.TransactionType
};
_db.Entry(transaction).State = EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
I've tried this for my get Edit, but it returns the same thing each time and not the one specified on my view. Ex. If click edit for Client D, it will pull up the edit screen for Client A and I cannot save it. I have an edit and delete button in my viewable table next to each transaction using an #Html.ActionLink().
public ActionResult Edit(TransactionViewModel viewModel)
{
if (ModelState.IsValid)
{
var transactions = from t in _db.Transactions
join c in _db.Clients
on t.ClientId equals c.ClientId
select new TransactionViewModel() { Clients = c, Transaction = t };
return View(transactions.FirstOrDefault());
}
return RedirectToAction("Index");
}
Any help would be appreciated. Thanks!

I bet that view is being cached. There are many different ways to influence caching in the controller. If you want to simply remove cacheing, in your case for editing, then decorate that action with the following:
[OutputCache(NoStore = true, Duration = 0)]
public ActionResult Edit(TransactionViewModel viewModel)
[OutputCache(NoStore = true, Duration = 0)]
public ActionResult Edit(int id = 0)
Note: You will have to clear cache to get the new view with the no cache set above.

Your Get Edit method should still accept an int ID to select the correct record form the database and it should return the view model.
something like this:
public ActionResult Edit(int id = 0)
{
var transactions = from t in _db.Transactions
join c in _db.Clients
on t.ClientId equals c.ClientId
where t.id == id
select new TransactionViewModel() { Clients = c, Transaction = t };
return View(transactions.FirstOrDefault());
}

Related

refresh a View page

In my page, I show an order with its products and price for each product in this
order, the user is able to change the price of each product.
The function for changing the price is working well but my problem is that the user must refresh the page to see the price is updated.
Is there any way to refresh the view and at the same action that update the price.
function for updating price:
public ActionResult UPPDATEPrise(int VaraId, int pris, int kundId)
{
int _Orderid = GetLastOrderId();
SqlConnection conn = new SqlConnection("Data Source=ENTERPRISE-PC;Initial Catalog=Fakturor;Integrated Security=True");
String command = "UPDATE [Fakturor].[dbo].[Varor] SET pris="+pris+" WHERE [id]="+VaraId+"";
SqlCommand cmd = new SqlCommand(command,conn);
conn.Open();
cmd.ExecuteNonQuery();
return RedirectToAction("UdateOrderDetails", new { kundId = kundId, OrderId = _Orderid });
}
Here my action that returns to the view:
public ActionResult UdateOrderDetails(int kundId, int OrderId)
{
//Orders procuts
DataClasses1DataContext db = new DataClasses1DataContext();
var t1 = (from p in db.Varors
join
op in db.OrderVarors on p.id equals op.IdVara
where op.IdOrder == OrderId
select p).ToList();
ViewBag.OrderItems = t1;
//customer details
ViewBag.id= kundId;
//Order id
ViewBag.OrderId = OrderId;
// All products
ViewBag.varor=HamtarVaror();
return View("Create");
}
Sounds like the browser is caching the page on direct. Not sure this will work but as an example of how to prevent caching (not the best implementation, just an example):
Set a flag that something was updated in tempdata.
public ActionResult UPPDATEPrise(int VaraId, int pris, int kundId)
{
// ALL YOUR CURRENT CODE....
TempData["IsCacheDisabled"] = true;
return RedirectToAction("UdateOrderDetails",
new { kundId = kundId, OrderId = _Orderid });
}
Check for it and update cache values:
public ActionResult UdateOrderDetails(int kundId, int OrderId)
{
// ALL YOUR CURRENT CODE....
if (TempData["IsCacheDisabled"] != null
&& (bool)TempData["IsCacheDisabled"])
{
var cache = HttpContext.Response.Cache;
cache.SetExpires(DateTime.UtcNow.AddDays(-1));
cache.SetValidUntilExpires(false);
cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
cache.SetCacheability(HttpCacheability.NoCache);
cache.SetNoStore();
}
return View("Create");
}

Save userid on database when create new object

I have a Controller where on the Create action I need the user ID.
Here's the controller.
public ActionResult Create(MyCreateViewModel model)
{
if (ModelState.IsValid)
{
var myobject = new MyObject
{
Attrib1 = DateTime.Now.Date,
Attrib2 = model.Etichetta,
UserId = // I need the user ID...
};
// Save the object on database...
return RedirectToAction("Index");
}
return View(model);
}
I'm using the UserProfile table provided with the SimpleMembership of MVC 4.
Which is the best practice in MVC 4 to manage the userID across the application?
Do I have to include a User attribute inside every Entity class?
Should I use a Session[] variable or what?
You can use this line to get the userId from the UserProfiles table.
var userId = WebSecurity.GetUserId(HttpContext.Current.User.Identity.Name);
You can also use this function to get the users complete profile, including any custom columns you may be populating.
public static UserProfile GetUserProfile()
{
using (var db = new UsersContext())
{
var userId = WebSecurity.GetUserId
(HttpContext.Current.User.Identity.Name);
var user = db.UserProfiles
.FirstOrDefault(u => u.UserId == userId);
if (user == null)
{
//couldn't find the profile for some reason
return null;
}
return user;
}
}

How to Modify view Model returned from base Controller (MVC4)

I am trying to implement a base controller, app services, repository design. I am new to this level of OO design but have gotten it pretty much complete. The remaining hurdle is how to handle extending my base controller.
My Goals:
have a base controller that can stand on its own...i.e. you could have a specific controller inherit from it but itself be empty and have it work.
In cases where I need to extend the base controller, have the
ability to do so in the specific controller.
Here is what I have:
Base Controller:
public class BaseControllerSingle<TRepository, TViewModelSingle> : BaseController
...
// GET: /InventoryMgmt/ManageItems/Edit/5
public virtual ActionResult Edit(
int id = 0,
string pageTitleNoun = "",
Expression<Func<TRepository, bool>> predicate = null
)
{
TViewModelSingle viewModelSingle = new TViewModelSingle();
ViewBag.Mode = "EDIT";
if (id == 0) //Add new company mode
{
viewModelSingle = _baseAppServSingle.CreateNewViewModel(CurrentUserId);
ViewBag.Header = "Create New " + pageTitleNoun;
ViewBag.Mode = "NEW";
return View(viewModelSingle);
}
//else edit existing record mode
viewModelSingle = _baseAppServSingle.CreateEditViewModel(id, predicate);
ViewBag.Header = "Edit " + pageTitleNoun;
return View(viewModelSingle);
}
And my specific controller. Note the code in this is incorrect (specifically"ItemViewModel viewModel = actionResult(ItemViewModel);"...but trying to show what I am attempting, which is essentially to extract the view model from the action result, manipulate it further, then return it.
public class ManageItemsController : BaseController
...
// GET: /InventoryMgmt/ManageItems/Edit/5
public ActionResult Edit(int id = 0)
{
ActionResult actionResult = GetBaseControllerSingle().Edit(
"Material",
id,
x => x.Id == id && x.CompanyId == CurrentCompanyId);
ItemViewModel viewModel = actionResult(ItemViewModel);
if (id == 0)
{
viewModel = _manageItemsAppServ.CreateNewViewModel(viewModel, CurrentCompanyId);
}
viewModel.DDLOptions = _manageItemsAppServ.CreateFilterOptionsViewModel(CurrentCompanyId);
return View(viewModel);
}
I have decided to re-write some of the code to remove this necessity. I think maybe it could be done with Ninject...but that's not something I wanted to get into right now

Populate Viewmodel inside an IF statement?

Im trying to populate a viewmodel based on the value from the querystring. Heres my controller:
public ViewResult Index(int? ShiftStatusID)
{
//Get logged in User
User user = _accountService.GetUser(_formsAuthService.GetLoggedInUserID());
if (ShiftStatusID == null) // Get all shifts
{
ViewModelShiftList viewModel = new ViewModelShiftList
{
Shifts = _shiftService.GetShifts(user.organisationID.Value).ToList()
};
}
else // Get shifts by status id
{
ViewModelShiftList viewModel = new ViewModelShiftList
{
Shifts = _shiftService.GetShiftsByStatus(user.organisationID.Value, ShiftStatusID).ToList()
};
}
return View(viewModel);
}
So it wont let me return the viewmodel to the view, saying "viewmodel does not exist in the current context". It wont let me declare the view model outside the if statement. How should this be done?
Try to move out if statement in your viewresult.
Here is a code example which should be working fine:
public ViewResult Index(int? ShiftStatusID)
{
//Get logged in User
User user = _accountService.GetUser(_formsAuthService.GetLoggedInUserID());
var viewModel = new ViewModelShiftList();
if (ShiftStatusID.HasValue)// Get shifts by status id
{
viewModel.Shifts = _shiftService.GetShifts(user.organisationID.Value).ToList();
}
else // Get all shifts
{
viewModel.Shifts = _shiftService.GetShiftsByStatus(user.organisationID.Value, ShiftStatusID).ToList();
}
return View(viewModel);
}
Clean up your code, remove duplicate lines:
public ViewResult Index(int? ShiftStatusID)
{
//Get logged in User
User user = _accountService.GetUser(_formsAuthService.GetLoggedInUserID());
List<Shift> shifts;
if(ShiftStatusID == null)
shifts = _shiftService.GetShifts(user.organisationID.Value).ToList();
else
shifts = _shiftService.GetShiftsByStatus(user.organisationID.Value, ShiftStatusID).ToList();
var viewModel = new ViewModelShiftList
{
Shifts = shifts
};
return View(viewModel);
}

Seat Reserving system

the Image shows how my tables are setup
Update
I have a working reserve seat and add to booking table now.
//
// POST: /Home/CreateBooking
public ActionResult CreateBooking(String id, DateTime date, DateTime time)
{
ViewData["username"] = User.Identity.Name;
ViewData["performanceDate"] = date;
ViewData["Venue"] = id;
BookingCreate model = new BookingCreate();
model.Seats = (from c in _db.Seat
where c.venue == id
select c);
return this.View(model);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateBooking(BookingCreate bookingCreate, IList<String> seatNumber)
{
Customer theCustomer
= (from c in _db.Customer
select c).First<Customer>(c => c.username == bookingCreate.customer);
//performance details for the performance selected by the user
Performance thePerformance
= (from p in _db.Performance
select p).FirstOrDefault<Performance>(p => p.performanceDate == bookingCreate.performanceDate || p.performanceTime == bookingCreate.performanceTime || p.venue == bookingCreate.venue);
//performance details for the performance selected by the user
Performance seatbooking
= (from p in _db.Performance
select p).FirstOrDefault<Performance>(p => p.performanceDate == bookingCreate.performanceDate || p.performanceTime == bookingCreate.performanceTime || p.venue == bookingCreate.venue);
var now = DateTime.UtcNow;
var bookingToCreate = new Booking();
bookingToCreate.bookingDate = now;
bookingToCreate.bookingTime = now;
bookingToCreate.bookingType = "Web";
bookingToCreate.collect = true;
bookingToCreate.Customer = theCustomer;
bookingToCreate.Performance = thePerformance;
_db.AddToBooking(bookingToCreate);
_db.SaveChanges();
var bookingnumber = (from p in _db.Booking
select p.bookingNo);
foreach (var displaySeat in seatNumber)
{
Seat theseat
= (from c in _db.Seat
select c).FirstOrDefault<Seat>(c => c.seatNumber == displaySeat);
var seatBooking = new SeatBooking();
seatBooking.Booking = bookingToCreate;
seatBooking.Seat = theseat;
_db.AddToSeatBooking(seatBooking);
_db.SaveChanges();
}
return RedirectToAction("ShowsIndex");
}
The code ensures that the correct venue's seats are displayed and that the logged in user and selected performance is chosen.
What i am stuck with is..
I am currently outputting the seats as checkboxes
with
BookingCreate model = new BookingCreate();
model.Seats = (from c in _db.Seat
where c.venue == id
select c);
But I would like for the checkboxes to show what seat number they relate to (at the moment they are just a blank checkbox)
And also how to stop showing seats that have been booked to stop duplication.
Thanks
I would do it this way (providing there are surrogate primary keys Customer.Id and Performance.Id)
public class BookingToCreateVM
{
public int BookingNo{get; set;}
//..etc - all necessary booking fields
public Guid UserId{get; set;}
public Guid PerformanceId{get; set;}
//data for something like dropdowns in view
public IList<Customer> Users{get; set;}
public IList<Performance> Performances{get; set;}
}
and the controller action
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateBooking(BookingToCreateVM bookingToCreateVM)
{
Customer theCustomer
= (from c in _db.Customer
select c).Single<Customer>(c=>c.Id == bookingToCreateVM.UserId);
Performance thePerformance
= (from p in _db.Performance
select p).Single<Performance>(p=> p.Id == bookingToCreateVM.PerformanceId);
var bookingToCreate = new Booking();
bookingToCreate.BookingNo= bookingToCreateVM.BookingNo;
//..etc - initialize all necessary fields
bookingToCreate.Customer = theCustomer;
bookingToCreate.Performance = thePerformance;
_db.AddToBooking(bookingToCreate);
_db.SaveChanges();
return RedirectToAction("ListBookings");
}

Resources