Question

Can someone explain to me why this doesn't work? I've read lots of posts about multiple submit buttons on one page, but I don't understand what's going on in the background. I've tried to follow what I see others doing in those posts, but none of it seems to work. I'm just trying to understand what is really going on here. I suspect it has something to do with what exactly happens when a page is posted.

Both buttons do a completely different thing. The first button posts the form. In the form's post code, it is then redirected to Vehicle/Index. The second button does not post the form, and goes directly to /Vehicle/CreateNewVehiclePart.

Here is what I want. I want both buttons to submit the form (so I can perform validation and save the changes to the Vehicle before moving on). Once the Vehicle data is saved, I want to move to /Vehicle/AddPartsToVehicle or /Vehicle/CreateNewVehiclePart based upon which button is clicked.

<table class="layouttable">
    <tr>
        <td>
            @using (Html.BeginForm("AddPartsToVehicle", "Vehicle", FormMethod.Post, null))
            {
                <input type="submit" value="Add Parts To Vehicle" />
            }
        </td>
        <td>
            @using (Html.BeginForm("CreateNewVehiclePart", "Vehicle", FormMethod.Post, null))
            {
                <input type="submit" value="Create New Vehicle Part" />
            }
        </td>
    </tr>
</table>

Here is the Vehicle model:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Globalization;


namespace ShopLog.Models
{
    public class Vehicle
    {
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid VehicleID { get; set; }

    [Timestamp]
    public Byte[] Timestamp { get; set; }

    [Required]
    [Display(Name = "Vehicle Name")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string VehicleName { get; set; }

    [Display(Name = "Assigned To")]
    [MaxLength(30, ErrorMessage= "The {0} must be no more than {2} characters long.")]
    public string AssignedTo { get; set; }

    [Display(Name = "ID Number")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string IDNumber { get; set; }

    [Display(Name = "Active")]
    public bool Active { get; set; }

    [Display(Name = "Sign Out Vehicle")]
    public bool SignOutVehicle { get; set; }

    [Display(Name = "Have Title")]
    public bool HaveTitle { get; set; }

    [Display(Name = "Mileage or Hours")]
    public int? MileageOrHours { get; set; }

    [Display(Name = "Make")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string Make { get; set; }

    [Display(Name = "Model")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string Model { get; set; }

    [Display(Name = "Year")]
    public int? Year { get; set; }

    [Display(Name = "Engine")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string Engine { get; set; }

    [Display(Name = "Transmission Gears")]
    public int? TransmissionGears { get; set; }

    [Display(Name = "VIN")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string VIN { get; set; }

    [Display(Name = "Serial Number")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string SerialNumber { get; set; }

    [Display(Name = "Color")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string Color { get; set; }

    [Display(Name = "Air Filter")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string AirFilter { get; set; }

    [Display(Name = "Engine Oil Filter")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string EngineOilFilter { get; set; }

    [Display(Name = "Fuel Filter")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string FuelFilter { get; set; }

    [Display(Name = "Transmission Oil Filter")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string TransmissionOilFilter { get; set; }

    [Display(Name = "HydraulicOilFilter")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string HydraulicOilFilter { get; set; }

    [Display(Name = "Interior A/C Filter")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string InteriorACFilter { get; set; }

    [Display(Name = "Differential Oil")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string DifferentialOil { get; set; }

    [Display(Name = "Transmission Oil")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string TransmissionOil { get; set; }

    [Display(Name = "Engine Oil")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string EngineOil { get; set; }

    [Display(Name = "Tire Size")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string TireSize { get; set; }

    [Display(Name = "Tire Pressure")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string TirePressure { get; set; }

    [Display(Name = "Smog Due Date")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:d}")]
    public DateTime? SmogDue { get; set; }

    [Display(Name = "Registration Due Date")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:d}")]
    public DateTime? RegistrationDue { get; set; }

    [Display(Name = "Insurance Due Date")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:d}")]
    public DateTime? InsuranceDue { get; set; }

    [Display(Name = "License Plate")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string LicensePlate { get; set; }

    [Display(Name = "Owner")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string Owner { get; set; }

    [Display(Name = "Previous Owner")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string PreviousOwner { get; set; }

    [Display(Name = "Date Acquired")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:d}")]
    public DateTime? DateAcquired { get; set; }

    [Display(Name = "Notes")]
    [DataType(DataType.MultilineText)]
    public string Notes { get; set; }

    [Required(ErrorMessage="Vehicle Type is required.")]
    public Guid VehicleTypeID { get; set; }
    public Guid? TransmissionTypeID { get; set; }

    //A vehicle can only have one VehicleType and one TransmissionType
    [Display(Name = "Vehicle Type")]
    public virtual VehicleType VehicleType { get; set; }

    [Display(Name = "Transmission Type")]
    public virtual TransmissionType TransmissionType { get; set; }


    //A vehicle can have many Parts
    [Display(Name = "Parts")]
    public virtual ICollection<Part> Parts { get; set; }

    //A vehicle can have many Warranties
    [Display(Name = "Warranties")]
    public virtual ICollection<Warranty> Warranties {get; set; }
}

}

Here is the Part model:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Globalization;

namespace ShopLog.Models
{
    public class Part
    {
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid PartID { get; set; }

    public string Name { get; set; }
    public decimal Cost { get; set; }

    [DataType(DataType.MultilineText)]
    public string Notes { get; set; }

    //A Part can belong to many Vehicles
    public virtual ICollection<Vehicle> Vehicles { get; set; }
    }
}
Was it helpful?

Solution

I tried this in a simple project

@model MvcApplication2.Models.LogOnModel

@{
    ViewBag.Title = "Home Page";
}

@using (Html.BeginForm("About", "Home", FormMethod.Post, null))
{
    <input type="submit" name="btn2" value="About" />
    @Html.TextAreaFor(m => m.UserName)
}

@using (Html.BeginForm("Index", "Home", FormMethod.Post, null))
{        
    <input type="submit" name="btn1" value="Index" />
    @Html.TextAreaFor(m => m.UserName)
}

public class HomeController : Controller
{
    [HttpPost]
    public ActionResult Index(LogOnModel a)
    {
        ViewBag.Message = "Welcome to ASP.NET MVC!";


        return View();
    }

    [HttpGet]
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult About(LogOnModel a)
    {

        return View();
    }
}

From what I can tell this works out of the box. I would check your routes...

OTHER TIPS

Here's how I would do the second part, at least. I'll come back and update if I figure out the first. Inside your "CreateNewVehiclePart", above the submit button, render a partial view:

@using (Html.BeginForm("CreateNewVehiclePart", "Vehicle", FormMethod.Post, null))
{
    @Html.Partial("AddPart", new ShopLog.Models.Part())
    <input type="submit" value="Create New Vehicle Part" />
}

The partial view "AddPart" would be like this:

@model ShopLog.Models.Part
@Html.EditorForModel()

Then in the controller, "CreateNewVehiclePart" would handle the post-- just add the part to the database, and redirect back to your original view.

EDIT: Ok, here's what I would do for the first part, also a partial view. Setup your form with a hidden field with the Vehicle ID, and a drop-down list for the parts:

@using (Html.BeginForm("AddPartsToVehicle", "Vehicle", FormMethod.Post, null))
(
    @Html.HiddenFor(model=>model.VehicleID)
    @Html.Partial("SelectPart", PartsList)
    <input type="submit" value="Add Parts To Vehicle" />
}

(Note that "PartsList" is something you'll have to set up in your code block at the top-- just a list of all available parts.) Then the partial view "SelectPart" would be like this:

@model IEnumerable<ShopLog.Models.Part>
@Html.DropDownList("part_id", Model.Select(m=>new SelectListItem() { Text = m.Name, Value = m.PartID.ToString() }))

Then again, as before, your "AddPartsToVehicle" would handle just those two parameters, and add the part with ID part_id to the vehicle.

Obviously I have left some gaps to fill in here, but I think this is a decent approach ...

I ended up using a combination of the two answers on this page. The ultimate problem was that I had a Save() button at the top of the page that was was not wrapped in its own "@Using Html.BeginForm{}". "TGH" helped me to map out where my POST code was actually going. That's what led me to solve the ultimate problem.

Using partial forms really helped me to make the application more concise (fewer page redirects). "dbaseman" helped me to get these set up correctly.

Thanks to both of you!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top