Calling httppost actionresult from inside a view using a button

你说的曾经没有我的故事 提交于 2019-12-20 04:50:22

问题


I have a project to make an online shop between users (post a product, buy, etc.) using a database. In this project I have a view called "ShoppingCart":

@model IEnumerable<MyFirstProject.Models.Product>

@{
    ViewBag.Title = "ShoppingCart";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Your Shopping Cart</h2>



@if (Model == null)
{
    <div style="float:left">Your cart is empty.</div>
    <div>
        Total payment: 0
    </div>
}
else
{
    decimal tPrice = 0;
    <div>
    <table style="float:left">
        @foreach (var product in Model)
        {
            tPrice = tPrice + product.Price;
            { Html.RenderPartial("ProductLine", product);}
        }
    </table>
        </div>
    <div>
        Total payment: @tPrice
    </div>
}

It receives a list of products which the user decided to buy and displays them (not the important part). I need to add a button which will send the list to an action result in the "ShoppingController":

[HttpPost]
        public ActionResult ShoppingCart(List<Product> bought)
        {
            if (ModelState.IsValid)
            {
                foreach (var listP in bought.ToList())
                {
                    foreach (var databaseP in db.Products.ToList())
                    {
                        if (listP.ProductID == databaseP.ProductID)
                        {
                            databaseP.State = 1;
                            db.SaveChanges();
                            break;
                        }
                    }
                }
                return RedirectToAction("Index");
            }

            else
            {
                return View(bought);
            }
        }

"State" indicates if the product was bought or not (0=not bought, 1=bought), db is the database


回答1:


If you wan't to post any data from a view to an action method, you should keep that data in form elements and keep that in a form. Since you want to post a collection of items, You may use Editor Templates.

Let's start by creating a view model.

public class ShoppingCartViewModel
{
    public decimal TotalPrice { set; get; }
    public List<Product> CartItems { set; get; }
}

public class Product
{
    public int Id { set; get; }
    public string Name { set; get; }
}

Now in your GET action, you will create an object of the ShoppingCartViewModel, load the CartItems property and send to the view.

public ActionResult Index()
{
    var cart = new ShoppingCartViewModel
    {
        CartItems = new List<Product>
        {
            new Product   { Id = 1, Name = "Iphone" },
            new Product   { Id = 3, Name = "MacBookPro" }
        },
        TotalPrice = 3234.95
    };
    return View(cart);
}

Now i will create an EditorTemplate. To do that, Go to your ~/Views/YourControllerName folder, and Create a directory called EditorTemplates and add a view with name Product.cshtml

The name of the file should match with the name of the type.

Open this new view and add the below code.

@model YourNamespace.Product
<div>
    <h4>@Model.Name</h4>
    @Html.HiddenFor(s=>s.Id)
</div>

You can keep the display however you want. But the important thing is, We need to keep a form field for the productId. We are keeping that in a hidden field here.

Now let's go back to our main view. We need to make this view strongly typed to our ShoppingCartViewModel. We will use the EditorFor html helper method in this view to call our editor template

@model ReplaceYourNamespaceHere.ShoppingCartViewModel
@using (Html.BeginForm())
{       
    @Html.EditorFor(x => x.CartItems)
    <p>Total : @Model.TotalPrice</p>
    <input type="submit" />
}

And in your HttpPost action method, We will have a paramer of type ShoppingCartViewModel. When the form is submitted, MVC Model binder will map the posted form values to an object of ShoppingCartViewModel.

[HttpPost]
public ActionResult Index(ShoppingCartViewModel model)
{
    foreach (var item in model.CartItems)
    {
        var productId = item.Id;
        // to do  : Use productId and do something
    }
    return RedirectToAction("OrderSucessful");
}

You can iterate through the CartItems collection and get the Id of the Products and do whatever you want.

If you wan't to allow the user to edit the items (using a check box) in this page, Take a look at this answer. It is basically same, but you add a boolean property to Product class and use that for rendering a checkbox.



来源:https://stackoverflow.com/questions/34364990/calling-httppost-actionresult-from-inside-a-view-using-a-button

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!