MVC的ViewModels和URL生成 [英] MVC ViewModels and url generation

查看:99
本文介绍了MVC的ViewModels和URL生成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新来的MVC和揣摩一些最佳实践。就在今天,我发现,当我宣布一个控制器方法,像这样:

 公共类的TestController:控制器
{
    公共类视图模型
    {
        公共字符串myvalue的{搞定;组; }
    }    公众的ActionResult指数(视图模型VM)
    {
        返回查看(VM);
    }
}

然后,参数 myvalue的不仅可以通过与 vm.MyValue = someValue中的查询参数,而且还与 myvalue的= someValue中。我喜欢这样,因为这样我可以生成一个URL到控制器的方法以

  Url.Action(指数,VM)

这是更名号,比类似

安全

  Url.Action(指数,新的{VM = VM})

我想我不得不写pviously $ P $。由于控制器会认为的非常视图模型,我甚至可以写

  @ Html.HiddenFor(VM => vm.MyValue)

在我看来,一个得到正确的名称。

现在这里的地方我结结巴巴:

视图的模型和控制器方法的参数模式很少会发生同样的事情,因为通常控制器会为视图获取更多的数据。

如果我介绍第二个模型,要么参数模型包括一个视图模型或其他方式轮,我输的有名称匹配的美丽,简单的方式上面显示:

 公共类的TestController:控制器
{
    公共类ParameterModel
    {
        公共字符串myvalue的{搞定;组; }
    }    公共类视图模型
    {
        公共ParameterModel ParameterModel {搞定;组; }
    }    公众的ActionResult指数(ParameterModel时)
    {
        VAR VM =新视图模型(){ParameterModel = PM};        返回查看(VM);
    }
}

现在,在视图中,我不得不写

  @ Html.HiddenFor(VM => vm.ParameterModel.MyValue)

这将创建 ParameterMode.MyValue = someValue中的参数字符串,这是不对的。

这是因为如果MVC被设计为期望视图的模型是正是被送入控制器方法 - 这往往并非如此

但显然没有解决这个办法吗?


解决方案

您已经触及到我这里的框架大的抱怨之一。因为视图键入一个特定的模式(姑且称之为显示模式)和所有的工具,用于创建表单都基于这种类型,它强烈建议您使用相同的模型,像你一样对你的参数的显示。

这不仅笨重,但它会导致其他问题 - 都在填充GET操作将不会对形式的帖子,除非你有隐藏字段坚持他们的属性,所以能够只需再次返回该视图的错觉显示的ModelState 错误会立即打破了。

这是你显示用户可能没有像你希望用户给你回(除非你正在构建大平台的形式)什么事实是该框架的主要疏漏之一。

一个想法是,你可以通过使用谐音为您的形式缓解这个问题:

  @model MyDisplayModel&所述p为H.; @ Model.SomeDisplayProperties&下; / P>@ Html.Partial(MyForm的新MyPostModel())

那么你的部分观点可以关注一下:

  @model MyPostModel@ Html.TextBoxFor(M = GT; m.SomeProperty)

这应该,我相信,产生正确的名称属性匹配到接受 MyPostModel 。

在的情况下,这是不是这样的,你基本上有两种选择:


  • 平展的GET和POST模式出到一件事,接受它的不雅,你将有很多空的。

  • 为您的文章操作创建不同的模型,要么尝试,使性能匹配在您的GET模型或手动构建HTML。

I'm new to MVC and try to figure out some best practices. Just today I discovered that when I declare a controller method like so:

public class TestController : Controller
{
    public class ViewModel
    {
        public String MyValue { get; set; }
    }

    public ActionResult Index(ViewModel vm)
    {
        return View(vm);
    }
}

Then, the parameter MyValue can not only passed in with a query argument of vm.MyValue=somevalue, but also with MyValue=somevalue. I like that because then I can generate a url to that controller method with

Url.Action("index", vm)

which is more name safe than something like

Url.Action("index", new { vm = vm })

which I thought I had to write previously. Since the controller takes the very view model of the view, I can even write

@Html.HiddenFor(vm => vm.MyValue)

in my view an get the correct names.

Now here's where I'm stumbling:

The view's model and the controller method's "parameter model" will rarely be the same thing, because normally the controller will fetch additional data for the view.

If I introduce a second model, and have either the parameter model include a view model or the other way round, I lose the beautiful, simple way of have the names match as showed above:

public class TestController : Controller
{
    public class ParameterModel
    {
        public String MyValue { get; set; }
    }

    public class ViewModel
    {
        public ParameterModel ParameterModel { get; set; }
    }

    public ActionResult Index(ParameterModel pm)
    {
        var vm = new ViewModel() { ParameterModel = pm };

        return View(vm);
    }
}

Now, in the view, I had to write

@Html.HiddenFor(vm => vm.ParameterModel.MyValue)

which creates an argument string of ParameterMode.MyValue=somevalue, which is wrong.

It's as if MVC is designed to expect the view's model to be exactly what is passed into controller methods - which is often not the case.

But clearly there is way around this?

解决方案

You've touched on one of my big gripes with the framework here. Because the view is typed to a particular model (let's call it the "display" model) and all of your tools for creating forms are based on this type, it strongly encourages you to use the same model for your parameters as you did for your display.

This is not only unwieldy but it leads to other problems - properties that were populated on GET actions won't be on form posts unless you persisted them with hidden fields, so the illusion of being able to just return the view again to display ModelState errors is immediately broken.

The fact that what you show the user is probably nothing like what you want the user to give you back (unless you are building big flat forms) is one of the major oversights of the framework.

One thought is that you could alleviate the problem by using partials for your forms:

@model MyDisplayModel

<p>@Model.SomeDisplayProperties</p>

@Html.Partial("MyForm", new MyPostModel())

Then your partial view can look like:

@model MyPostModel

@Html.TextBoxFor(m => m.SomeProperty)

Which should, I believe, generate the correct name attributes to match up to a controller action that accepts a MyPostModel.

In situations where this isn't the case, you basically have two options:

  • Flatten your GET and POST models out into one thing and accept that it's inelegant and you will have lots of nulls.
  • Create a different model for your POST actions and either try and make the properties match those in your GET model or build your HTML manually.

这篇关于MVC的ViewModels和URL生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆