0

I'm trying to have multiple actions accessible from my Index page instead of having a separate view for each. But I'm not having much luck and I'm pretty much stuck.

My BeginForm can't resolve action Create nor can it resolve the controller CategoriesController.

This is my controller:

public class CategoriesController : Controller
{
    private readonly ApplicationDbContext _db = new ApplicationDbContext();

    public async Task<ActionResult> Index()
    {
        return View(await _db.Categories.ToListAsync());
    }

    public ActionResult Create()
    {
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Create([Bind(Include = "Id,Name")] Category category)
    {
        if (ModelState.IsValid)
        {
            _db.Categories.Add(category);
            await _db.SaveChangesAsync();
            return RedirectToAction("Index");
        }

        return View(category);
    }

    public async Task<ActionResult> Delete(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Category category = await _db.Categories.FindAsync(id);
        if (category == null)
        {
            return HttpNotFound();
        }
        return View(category);
    }

    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> DeleteConfirmed(int id)
    {
        Category category = await _db.Categories.FindAsync(id);
        _db.Categories.Remove(category);
        await _db.SaveChangesAsync();
        return RedirectToAction("Index");
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _db.Dispose();
        }
        base.Dispose(disposing);
    }
}

And this is my view

@using MultipleActionsSameView.Controllers
@model IEnumerable<MultipleActionsSameView.Models.Category>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.ActionLink("Delete", "Delete", new { id=item.Id })
        </td>
    </tr>
}

</table> 

@using (Html.BeginForm("Create", "CategoriesController", FormMethod.Post))
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Category</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}
Paul Zahra
  • 9,522
  • 8
  • 54
  • 76
foo bar
  • 180
  • 3
  • 17

3 Answers3

3

use "Categories" instead of "CategoriesController"

 @using (Html.BeginForm("Create", "Categories", FormMethod.Post))
 {
      //your code
 }

sample here: BeginForm

VJPPaz
  • 917
  • 7
  • 21
1

Have you tried to drop the "Controller" suffix of "CategoriesController" in Html.BeginForm ?

Mik
  • 1,306
  • 1
  • 10
  • 14
1

To have multiple submit buttons in one view do the following:

Create an attribute...

using System;
using System.Reflection;
using System.Web.Mvc;

/// <summary>
/// The MultipleButtonAttribute class is a custom attribute to cater for a view form with multiple submit buttons.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MultipleButtonAttribute : ActionNameSelectorAttribute
{
    public string Name { get; set; }
    public string Argument { get; set; }

    /// <summary>Determines whether the action name is valid in the specified controller context.</summary>
    /// <param name="controllerContext">The controller context.</param>
    /// <param name="actionName">The name of the action.</param>
    /// <param name="methodInfo">Information about the action method.</param>
    /// <returns>True if the action name is valid in the specified controller context; otherwise, false.</returns>
    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
    {
        var isValidName = false;
        var keyValue = string.Format("{0}:{1}", this.Name, this.Argument);
        var value = controllerContext.Controller.ValueProvider.GetValue(keyValue);

        if (value != null)
        {
            controllerContext.Controller.ControllerContext.RouteData.Values[this.Name] = this.Argument;
            isValidName = true;
        }

        return isValidName;
    }

Then in the view I have multiple submit buttons and a form pointing at the index action like so...

@using (Html.BeginForm("Index", "Categories", FormMethod.Get, new { id = "mainForm" }))
{
    <input type="submit" value="Create" name="action:Create" />
    <input type="submit" value="Edit" name="action:Edit" />
}

Then in my controller:

[HttpGet]
[MultipleButton(Name = "action", Argument = "Create")]
public ActionResult Create()

[HttpGet]
[MultipleButton(Name = "action", Argument = "Edit")]
public ActionResult Edit()
Paul Zahra
  • 9,522
  • 8
  • 54
  • 76
  • Is there any guide you know of that is good so I can read up more close to the subject? – foo bar Sep 15 '15 at 09:35
  • Have a read of http://blog.maartenballiauw.be/post/2009/11/26/Supporting-multiple-submit-buttons-on-an-ASPNET-MVC-view.aspx – Paul Zahra Sep 15 '15 at 09:41
  • and http://stackoverflow.com/questions/442704/how-do-you-handle-multiple-submit-buttons-in-asp-net-mvc-framework – Paul Zahra Sep 15 '15 at 09:42