ASP.NET MVC5控制器操作方法参数为null

时间:2017-01-26 14:05:57

标签: c# asp.net asp.net-mvc razor asp.net-mvc-5

是否可以从@Html.EditorFor

中修改发布到控制器操作的属性名称

我有一个视图,它们都显示一个对象列表和一个允许用户创建一个表单的表单。我只想在创建时回发新的对象值,而不是在可能的情况下回发整个视图模型。

视图的ViewModel结构如下所示:

public class GenericIndexViewModel
{
    public IEnumerable<GenericListViewModel> ExistingObjects { get; set; }
    public GenericCreateViewModel NewObject { get; set;
}

public class GenericCreateViewModel
{
    public string PropertyA { get; set; }
    public string PropertyB { get; set; }
}

在视图中,我循环浏览ExistingObjects以显示所有现有对象,而在下面我正在创建一个包含@Html.BeginForm("Index", "GenericController", FormMethod.Post)的表单,并在内部我有适当的@Html.EditorFor(m => m.NewObject.PropertyA)。查看下面的代码段:

@model Namespace.Models.Generic.GenericIndexViewModel
...
@if (Model.ExistingObjects.Any())
{
    // Display list of objects
}
...
@using (Html.BeginForm("Index", "GenericController", FormMethod.Post))
{
    @Html.ValidationSummary(true)

    <div class="field-holder">
        @Html.LabelFor(m => m.NewObject.PropertyA)
        @Html.EditorFor(m => m.NewObject.PropertyA)
    </div>

    <div class="field-holder">
        @Html.LabelFor(m => m.NewObject.PropertyA)
        @Html.EditorFor(m => m.NewObject.PropertyA)
    </div>

    <div>
        <input type="submit" value="Save" name="command" />
    </div>
}

动作方法签名如下:

[HttpPost]
public ActionResult Index(GenericCreateViewModel model) { ... }

当我提交表单时,虽然model参数为null,但它已成功点击操作方法。

当我检查帖子数据时,我可以看到属性以NewObject为前缀:

NewObject.PropertyA=test1&NewObject.PropertyB=test2

如何阻止前缀,或者让action方法将前缀属性识别为参数?

2 个答案:

答案 0 :(得分:2)

尝试将编辑器更改为

@SpringBootTest
@RunWith(SpringRunner.class)
public class SoapGatewayTest {

    private static final String XML_REPONSE = "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\"><S:Body>"
            // enrich your answer here
            // ...
            + "</S:Body></S:Envelope>";

    @Autowired
    @Qualifier("soapcall$child.wsgw.handler")
    private AbstractWebServiceOutboundGateway simpleWebServiceOutboundGateway;

    @Mock
    private WebServiceMessageSender messageSender;

    @Mock
    private WebServiceConnection wsConnection;

    @Test
    public void myMethodTest() {
        // mocking the WS SOAP gateway
        when(this.messageSender.createConnection(any(URI.class))).thenReturn(this.wsConnection);
        when(this.messageSender.supports(any(URI.class))).thenReturn(true);

        // the gateway will always respond with a static response
        doAnswer(new Answer<WebServiceMessage>() {
            public WebServiceMessage answer(InvocationOnMock invocation) throws InvalidXmlException, IOException {
                WebServiceMessageFactory factory = invocation.getArgumentAt(0, WebServiceMessageFactory.class);
                return factory.createWebServiceMessage(new ByteArrayInputStream(XML_REPONSE.getBytes()));
            }
        }).when(this.wsConnection).receive(any(WebServiceMessageFactory.class));

        this.simpleWebServiceOutboundGateway.setMessageSender(this.messageSender);

        // run the code to be tested here
        // ...
    }
}

将您的发布操作更改为

@Html.EditorFor(m => m.NewObject.PropertyA)

然后访问[HttpPost] public ActionResult Index(GenericIndexViewModel model) { ... } 以获取所需的model.NewObject

或者您可以尝试使用:

GenericCreateViewModel

并在POST方法中继续接收<div class="field-holder"> <label>PropertyA</label> <input type="text" name="PropertyA" /> </div> <div class="field-holder"> <label>PropertyB</label> <input type="text" name="PropertyB" /> </div> <div> <input type="submit" value="Save" name="command" /> </div> 对象。

GenericCreateViewModel

这只是达到预期效果的一种方法。

答案 1 :(得分:0)

默认表单行为会将完整模型发布回您的控制器,因此解决此问题的简便方法是将索引后方法中的参数更改为GenericIndexViewModel

如果您想保留c#方法,则需要覆盖数据格式化方式,并在onsubmit事件中自行发布帖子请求。