mvc beginform无法使路由覆盖工作

时间:2014-07-26 10:45:58

标签: c# asp.net-mvc

同样回答这个问题 Html.BeginForm with html attributes asp.net mvc4

我有一个视图的viewmodel,其中包含用于填充下拉列表和列表的集合。所以我不想回归它们,我只想返回模型对象。实际上,我只想返回该模型中的4个字段 - 但这是下一个问题。 通过做这个appraoch,我已经躲过了,但我没有运气,除非我提交整个viewmodel,在这个表格上是荒谬的,因为95%的信息被丢弃。

无论如何,我遇到的问题是我无法将创建帖子中返回的游戏事件变为null以外的任何事件。 create上的gameEvent参数为NULL。

也有点惊讶我还没有找到关于此的大量信息。

控制器:

    public ActionResult Create()
    {
        ...

        var createEventViewModel = new CreateEventViewModel()
        {
            Places = places,
            Characters = characters,
            Event = new GameEvent()
        };

        return this.View(createEventViewModel);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "Name,Description,EventType,Duration")] GameEvent gameEvent)
    {
        ...
    }

观点:

  @model Sisyphus.Web.Models.CreateEventViewModel

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

<h2>Create Event</h2>
<div class="row">
    <div class="col-lg-8">
        <section id="createEvent">
            @using (Html.BeginForm("Create", "Event",
                new
                {
                    GameEvent = Model.Event
                }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
            {
                @Html.AntiForgeryToken()
                @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                <div class="form-group">
                    @Html.LabelFor(m => m.Event.Name, new { @class = "col-md-2 control-label" })
                    <div class="col-md-10">
                        @Html.TextBoxFor(m => m.Event.Name, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.Event.Name, "", new { @class = "text-danger" })
                    </div>
                </div>

                <div class="form-group">
                    @Html.LabelFor(m => m.Event.Description, new { @class = "col-md-2 control-label" })
                    <div class="col-md-10">
                        @Html.TextAreaFor(m => m.Event.Description, 10, 30, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.Event.Description, "", new { @class = "text-danger" })
                    </div>
                </div>

                <div class="form-group">
                    @Html.LabelFor(model => model.Event.Duration, new { @class = "control-label col-md-2" })
                    <div class="col-md-10">
                        @Html.TextBoxFor(m => m.Event.Duration, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.Event.Duration, "", new { @class = "text-danger" })
                    </div>
                </div>

                <div class="form-group">
                    @Html.LabelFor(model => model.Event.EventType, new { @class = "control-label col-md-2" })
                    <div class="col-md-10">
                        @Html.EnumDropDownListFor(m => m.Event.EventType)
                    </div>
                </div>

                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <input type="submit" value="Create Event" class="btn btn-default" />
                    </div>
                </div>
            }
        </section>
    </div>
</div>

模特:

public class GameEvent
{
    public string Name { get; set; }

    public string Description { get; set; }

    public int Duration { get; set; }

    public EventType EventType { get; set; }
}

viewmodel :(已向下编辑删除了无关的成员

public class CreateEventViewModel
{
    public GameEvent Event { get; set; }
}

编辑: 好的,我刚试了这个

@using (Html.BeginForm("Create", "Event",
                new RouteValueDictionary()
                {
                    {"GameEvent", Model.Event}
                }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))

游戏事件现在不为空(其中的所有值都是) - 所以不是更接近

1 个答案:

答案 0 :(得分:2)

您的回发输入基于class CreateEventViewModel,例如

@Html.TextBoxFor(m => m.Event.Name, ...
@Html.TextAreaFor(m => m.Event.Description, ...

将生成以下html

<input id="Event_Name" name="Event.Name" value=....

但是,您的帖子操作方法的参数是GameEvent的类型,而不是CreateEventViewModel。如果您检查Response.Form.Keys,则会看到Event.NameEvent.Description等,但class GameEvent具有属性NameDescription等,因此值不能为由ModelBinder

匹配

您需要将发布方法更改为

public ActionResult Create(CreateEventViewModel model)
{
   GameEvent event = model.GameEvent;
  // do whatever with GameEvent

您还应该删除new {GameEvent = Model.Event} from the Html.BeginForm`方法

注意我排除了BindAttibute,因为在这种情况下我不认为它是必要的 - 你似乎想要GameEvent的所有属性,除非你为PlacesCharacters的属性创建输入,无论如何它们都将为null,并且由于您没有访问其他属性,因此没有质量分配漏洞。

其他替代方法是手动创建输入,以便正确映射属性,直接html

<input name="Name" value=@Model.Event.Name />
<input name="Description" value=@Model.Event.Desciption />

或使用助手

var Description = Model.Event.Description;
@Html.TextBoxFor(m => Description)