Passing newly created object to an another page - c#

I'm working on a mvc4 project and I cant seem to figure out how to pass a newly created object from one page to another page.
on page A
im submitting a form to the database which is creating a new object in placing it into the table.
but after the form is submitted I want a confirmation page to appear afterwards. I dont know how to pull the newly created object from the previous page that saved it to the database. I could call it with the Id that was made but I dont know how to call it without knowing the id
public ActionResult Pay(int id,Paid paid)
{
PaidAdapter cAdapter = new PaidAdapter();
paid.CId = id;
if (ModelState.IsValid)
{
cAdapter.StorePaid(paid);
return RedirectToAction("SubmitPayment");
}
return View(paid);
}
public ActionResult SubmitPayment(int id)
{
var cAdapter = new PaidAdapter();
var model = cAdapter.GetPaidViewModel(id);
return View(model);
}
public Paid StorePaid (Paid paid)
FContext db = new FContext();
paid= db.Paid.Add(paid);
db.SaveChanges();
//return the paidId
return paid;
}
public PaidViewModel GetPaidViewModel(int id)
{
var model = new PaidViewModel();
FContext db = new FContext();
model.Paid= db.Paid.Where(c => c.PaidId == id).FirstOrDefault();
return model;
}

Use the overload of RedirectToAction that accepts route parameters. Assuming you're using the default route and it has an id parameter the code would be:
return RedirectToAction("SubmitPayment", new { id = paid.PaidId });

Related

ASP.NET MVC5 problem in passing data between Controllers

I am building a basic Car Rental Application. The user can view the cars and click the Rent button. After clicking it, I need to return a new View which contains a form, that the user has to complete in order to finish the order. I am having problems passing the Car data as well as the Customer data between the controllers in order to complete the Rent.
On the main page, I have a Rent link under every car. Here is the code:
<div class="col-md-12">
<p>#Html.ActionLink("Rent", "Rent" , new { Id = car.Id})</p>
</div>
Rent method from HomeController
public ActionResult Rent(string id)
{
return RedirectToAction("Create", "Rents");
}
Create method from RentsController
[HttpPost]
public ActionResult Create(string carId, Rent rent)
{
if (!ModelState.IsValid)
return View();
var carToRent = context.Cars.SingleOrDefault(c => c.Id == carId);
if (carToRent == null)
return Content($"Car not found!");
rent.Car = carToRent;
var customer = context.Customers.SingleOrDefault(c => c.UserId == User.Identity.Name);
if (customer == null)
return Content($"Customer not found!");
rent.Customer = customer;
context.Rents.Add(rent);
context.SaveChanges();
return RedirectToAction("Index");
}
I am getting an HTTP 404 Error every time I try to access Rents/Create.
You can simplify what you're attempting to do. Main points to note are the following:
You don't need to link to the Rent action if all it does is
redirect to the Create action- just link to the Create action
directly. There is another overload of ActionLink that will let you specify
the controller (see below).
From what you've posted it doesn't look like the Create action
needs to take in a parameter for Rent rent- this can be created
inside the Create action and simplify the data that you need to
pass from view to controller.
Please see my comments in code for further explanantion:
View:
//call the Create action on the RentsController directly from the view
<div class="col-md-12">
<p>#Html.ActionLink("Rent", "Create", "Rents" , new { Id = car.Id }, null)</p>
</div>
Controller:
//modify signature to remove passing a Rent object it
//you can create this object inside of this method
//and do not need to pass one in so remove it from the method signature
[HttpPost]
public ActionResult Create(string carId)
{
if (!ModelState.IsValid)
return View();
var carToRent = context.Cars.SingleOrDefault(c => c.Id == carId);
if (carToRent == null)
return Content($"Car not found!");
var rent = new Rent(); //this line has been added since the method signature was changed
rent.Car = carToRent;
var customer = context.Customers.SingleOrDefault(c => c.UserId == User.Identity.Name);
if (customer == null)
return Content($"Customer not found!");
rent.Customer = customer;
context.Rents.Add(rent);
context.SaveChanges();
return RedirectToAction("Index");
}
and finally you can remove the following:
//delete this action entirely, if youre doing nothing other than redirecting
//to an action then just link directly to the action you want
//notice the ActionLink in the view is modified to hit the Create action directly
public ActionResult Rent(string id)
{
return RedirectToAction("Create", "Rents");
}
As you can see below you can pass parameters in RedirectToAction() method.
RedirectToAction(String, String, RouteValueDictionary)
Redirects to the specified action using the action name, controller name, and route values. Try to redirect Create action with the carId and Rent object.
I dont know using multiple post object, but you can post one post object like that
public class MyPostObject
{
public string carId { get; set; }
public Rent rent{ get; set; }
}
and post it like that
[HttpPost]
public ActionResult Create(MyPostObject myPostObject)
{
string carId=myPostObject.carId;
Rent rent = myPostObject.rent;
....
}
UPDATE : Or you can use multiple post object with Ajax
$("#btnSave").on('click', function () {
var url = '#Url.Action("Create", "Rent")';
//Rent class properties
var data=
{
Brand: 'Renault',
Model: 'Megan',
};
$.ajax({
url:url,
type:"POST",
data:{
carId:'12',
rent:data
},
datatype:'json',
ContentType:'application/json;utf-8'
}).done(function(resp){
alert('Success ' +resp);
}).error(function(err){
alert("Error " + err.status);
});
});
As mentioned in the comments, you will have to pass the required parameters into the redirect statement.
public ActionResult Rent(string id)
{
Rent rentItem = new Rent();
return RedirectToAction("Create", "Rents", new { carId = id, rent = rentItem});
}
You either have not passed the parameters or you are missing the below method if you are looking to return a view with your redirect
public ActionResult Create()
{
return View();
}

variable within controller returns null even after being set [duplicate]

I have a controller in ASP.NET MVC application.
private GipDbContext db = new GipDbContext();
private Employee employeeObj;
public ActionResult Edit(int? id)
{
Employee employee = db.Employees.Find(id);
//employeeObj SET TO ANOTHER OBJECT
employeeObj = employee;
return View(employee);
}
public PartialViewResult TimeSeriesData(int? tsdataid)
{
TimeSeriesData tsobject = new TimeSeriesData();
// employeeObj RETURNING NULL
foreach (var item in employeeObj.TimeSeriesData){
if (item.TimeSeriesDataID == tsdataid)
{
tsobject = item;
break;
}
}
The first method being called is Edit, then when TimeSeriesData is called employeeObj is returning null, even though it was set in the Edit method.. any ideas why?
Controllers are instantiated for each request. Once you request TimeSeriesData, the controller that was created for the request to Edit has already been disposed. If you need to hold on to a piece of data between requests, you must either put it in Session or TempData (both of which use sessions).

private member in controller returns null after being set in action result

I have a controller in ASP.NET MVC application.
private GipDbContext db = new GipDbContext();
private Employee employeeObj;
public ActionResult Edit(int? id)
{
Employee employee = db.Employees.Find(id);
//employeeObj SET TO ANOTHER OBJECT
employeeObj = employee;
return View(employee);
}
public PartialViewResult TimeSeriesData(int? tsdataid)
{
TimeSeriesData tsobject = new TimeSeriesData();
// employeeObj RETURNING NULL
foreach (var item in employeeObj.TimeSeriesData){
if (item.TimeSeriesDataID == tsdataid)
{
tsobject = item;
break;
}
}
The first method being called is Edit, then when TimeSeriesData is called employeeObj is returning null, even though it was set in the Edit method.. any ideas why?
Controllers are instantiated for each request. Once you request TimeSeriesData, the controller that was created for the request to Edit has already been disposed. If you need to hold on to a piece of data between requests, you must either put it in Session or TempData (both of which use sessions).

Changes to DbContext not saved - MVC Entity framework

I have created a database and then an MVC solution using VisualStudio Exrpess 2013 for WEB and
I created a ViewModel to display an Edit view with dropdown lists.
The view model includes just the property 'parlists' of type PartnerList, which is the model representing the main table of the database, and 2 properties of type SelectList which I use to create the dropdown lists in the view.
The code of the viewmodel is as follows:
public class FileStatusEdit
{
public SelectList HoldingsStatus { get; set; }
public SelectList RealGainStatus { get; set; }
public PartnerList parlists { get; set; }
}
In the controller I have the following code for the HttpGet edit method:
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var viewModel = new FileStatusEdit
{
HoldingsStatus = new SelectList(db.Statuses, "Status_ID", "Status1", db.PartnerLists.Where(p => p.IntermediaryID == id).Single().AssetDataSource.HoldingsFile.Status_ID),
RealGainStatus = new SelectList(db.Statuses, "Status_ID", "Status1", db.PartnerLists.Where(p => p.IntermediaryID == id).Single().AssetDataSource.RealGainFile.Status_ID),
parlists = db.PartnerLists
.Include(p => p.AssetDataSource)
.Where(p => p.IntermediaryID == id)
.Single()
};
if (viewModel.parlists == null)
{
return HttpNotFound();
}
return View(viewModel);
}
This code is working fine and the view is correctly displaying a form with the dropdown lists. I omit the view code as it is quite long and propably not relevant.
So far so good.
My Http Post Edit method, however, is not saving the changes to the database. The code is as follows:
[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public ActionResult EditPost(FileStatusEdit newParList)
{
if (TryUpdateModel(newParList.parlists, "",
new string[] { "Firstname", "Surname", "Category", "ClientID", "IntermediaryID", "ExternalRef", "RecordStatus", "Asset_Data_Source_ID", "New_Communication_Issued", "AssetDataSource", "HoldingsFile", "RealGainFile"}))
{
try
{
db.Entry(newParList.parlists).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
catch (RetryLimitExceededException)
{
ModelState.AddModelError("", "Unable to save changes.");
}
}
return View(newParList);
}
As you can see I am passing the viewmodel (newParList) to the EditPost method and then I update it using TryUpdateModel. By stepping into the debugging process I can see that the database record newParList.parlists is correctly updated with the user input, however when the step db.SaveChanges() is executed the program redirects to the Index view without saving the changes to the database.
I tried using Attach as suggested in some posts but I believe the attach step is already included in the line 'db.Entry(newParList.parlists).State = EntityState.Modified;' and that did not indeed solve the problem.
I examined a lot of posts and tried different solutions but none of them worked so I would appreciate some help.
I suspect you're missing the context add or update.
Here's an example of how I handle the creation of a new record.
For an update you would find the record first then save the changes.
public void SaveCreatedMessage(Message message)
{
var dbEntry = _context.Message.Add(message);
if (dbEntry != null)
{
// Create the new record
dbEntry.CustomerID = message.CustomerID;
dbEntry.MessageID = message.MessageID;
dbEntry.Description = message.Description;
dbEntry.Text = message.Text;
dbEntry.IsRead = message.IsRead;
dbEntry.CreatedOn = message.CreatedOn;
dbEntry.CreatedBy = message.CreatedBy;
_context.Message.Add(message);
}
_context.SaveChanges();
}
I think I found the solution. I was not updating the correct entity.
In my HttpPost Edit method I now replaced the following line:
db.Entry(newParList.parlists).State = EntityState.Modified;
with:
db.Entry(newParList.parlists.AssetDataSource.HoldingsFile).State = EntityState.Modified;
db.Entry(newParList.parlists.AssetDataSource.RealGainFile).State = EntityState.Modified;
Now my entities HoldingsFile and RealGainFile are updated after SaveChages() is executed.

How to Create an Action Method invoking two tables

Thanks in advance for your help. I cannot move forward creating or editing fields in asp.net mvc using two tables or more. As an example: I´ve been using MVC Music Store example to learn
//
// GET: /StoreManager/Create
public ActionResult Create()
{
var viewModel = new StoreManagerViewModel
{
Album = new Album(),
Genres = storeDB.Genres.ToList(),
Artists = storeDB.Artists.ToList()
};
return View(viewModel);
}
//
// POST: /StoreManager/Create
[HttpPost]
public ActionResult Create(Album album)
{
if (ModelState.IsValid)
{
//Save Album
storeDB.AddToAlbums(album);
storeDB.SaveChanges();
return RedirectToAction("Index");
}
// Invalid – redisplay with errors
var viewModel = new StoreManagerViewModel
{
Album = album,
Genres = storeDB.Genres.ToList(),
Artists = storeDB.Artists.ToList()
};
return View(viewModel);
}
This example takes into consideration that Album is only one table at the model. My main question resides in the way I have to code in order to include another table with FK to Album. As an example if AlbumVariant table - eg: field albumid- displays a FK to Album Table - eg: field albumid-.
I´ve been trying with
[Authorize]
public ActionResult Create(int? id)
{
var albumCreate= db.Album.Include(AlbumVariant)SingleOrDefault(a => a.AlbumId == id);
var viewModel = new AlbumViewModelCreate()
{
AlbumCreate = albumCreate,
};
}
but with no success. Any Help will be appreciated. brdgs
You have to understand that AlbumVariant table takes AlbumId as a foreign key that means AlbumId has to be generated first! You can try this:
storeDB.AddToAlbums(album);
storeDB.SaveChanges();
AlbumVariant av = new AlbumVariant {
...
AlbumId = album.Id //generates after calling the 1st save changes
}
storeDB.AddToAlbumVariant(av);
storeDB.SaveChanges();

Categories