简体   繁体   中英

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 .

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);
        });

    });

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");
}

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(); 
}

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});
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM