传递数据用行动C#MVC查看 [英] Pass data to view using action C# MVC

查看:113
本文介绍了传递数据用行动C#MVC查看的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前工作中,我们有很多同类机型的一个项目。我们让他们都来自同一个基础模型继承,我们也做了一个共同的控制器(基本的东西,如列表,添加,编辑等)处理示范基地。它的实际工作,并提出事容易让我们,但我有小问题,下拉菜单。

I'm currently working on a project in which we have a number of similar models. We made them all inherit from the same base model and we also made a common controller (basic stuff like list, adding, editing etc.) handles the base model. It actually works and made things easy for us, but I have small problem with dropdowns.

没有进入太多细节,这会使事情很容易对我来说,如果我可以从控制器传递数据使用动作来查看。事情是这样的:

Without going into much details, it would make things really easy for me if I could pass data from controller to view using an action. Something like this:

@Html.DropDownListFor(model => model.Xtypechild, Action("GetList", "XController"))

在哪里行动的GetList 收益的IEnumerable< SelectListItem>

这样我可以写code只有一次,并将其用于许多不同的控制器。

This way I could write the code just once and use it for a number of different controllers.

我知道这听起​​来很疯狂,但如果我试图用更传统的方法可以做到这一次我会下再结束与冗余$ C $和会失去一些我们继承控制器获得了优势。

I know it sounds crazy, but if I tried use one of more conventional ways to do this I would end up with redundant code again and would lose some of the advantage we gained from inheriting controllers.

我可以看到现在唯一的选择就是让的GetList 返回JSON的所有项目和填充使用Ajax / JS的下拉菜单。我也能有这样的返回包含下拉列表中选择局部视图的动作,但我不知道这是一个好主意。

The only alternative I can see right now is to make GetList return JSON with all the items and populate the dropdowns using Ajax/JS. I could also make an action that returns a partial view containing the dropdown, but I'm not sure if that's a good idea.

感谢您到目前为止所有的输入。最后,我用以下解决方案了:

Thank you far all the input. In the end I went with the following solution:

我们有一个服务类来处理数据库的操作对我们的模型。我只想补充一点,生成一个的IEnumerable℃的方法; SelectListItem> 来基本服务类。现在我通过了下拉菜单中的项目通过ViewBag(虽然它迫使我投他们回到了IEnumerable使用前视图)。我将它们分配给ViewBag在继承控制器的重写构造函数。

We had a services class for handling database operations for our models. I just add a method that generates a IEnumerable<SelectListItem> to the base services class. Now I pass the items for drop downs through ViewBag (though it forces me to cast them back to IEnumerable before use in the view). I assign them to ViewBag in the overridden constructor of the inherited controller.

我最好的咨询code的原作者,如果这个解决方案将确定为我们的项目,尽管他是在度假现在。对于现在这个将不得不这样做。在向上侧这种方法生产的小code,所以应该易于更换(如果我必须这样做)。

I've best consult the original author of the code if this solution will be ok for our project, though he is on holiday right now. For now this will have to do. On the up side this method produced little code, so it should be easy to replace (if I have to do so).

在code进化了一点,现在我有这样的事情在视图中(注意 INT?铸造是有,因为财产是int类型并且,否则它不会工作):

The code evolved a little bit and now I have something like this in the view (note the int? casting is there because the property was of type int and it wouldn't work otherwise):

Html.DropDownListFor(
        model => model.XId, 
        new SelectList((List<X>)ViewBag.Xs, "Id", "Name", (Model != null ? (int?)Model.XId : null)),
            " -- select -- ",
            null)

和像这样的控制器的重载构造函数里面:

And something like this inside of overridden constructor of the controller:

ViewBag.Xs = db.Xs.ToList();

这definitelly不落实在剃刀的下拉列表中的最佳方式,但它是执行这些项目的最佳途径。这样做的原因是:没有时间,使项目使用的ViewModels并重写基本控制器的一切行动来处理它们(以及为这些行动提供下拉菜单数据)

It's definitelly not the best way to implement dropdowns in razor, but it was the best way to implement them in the project. The reason for this was: there was no time to make the project use ViewModels and override all the actions of base controller to handle them (as well as provide data for the dropdowns in those actions).

在code,甚至进一步发展。这当然不是在控制器构造函数中执行查询,如果数据只是在景色极少数被用于一个好主意。所以,现在的构造包含等效的:

The code evolved even further. It's certainly not a good idea to execute queries in the controller constructor if the data will be used just in a handful of views. So now the constructor contains equivalent of:

ViewBag.Xs = (IQueryable<X>)db.Xs;

和视图:

Html.DropDownListFor(
        model => model.XId, 
        new SelectList((IQueryable<X>)ViewBag.Xs, "Id", "Name", (Model != null ? (int?)Model.XId : null)),
            " -- select -- ",
            null)

此方式,当一个观点实际上所需要的数据只执行查询。

This way the query is only executed when a view actually needs the data.

推荐答案

我当然不具有对视图模型的方法来填充的SelectList ,甚至同意如果呼叫控制器。这其中的原因很简单:是控制器的责任来填充一个模型,而不是周围的其他方法

I certainly don't agree with having a method on the view model to populate the SelectList, even if it is calling the controller. The reason for that is simple: it is the controller's responsibility to populate a model, not the other way around.

要处理这种情况最好的办法是让您的控制器上的方法,它可以建立列出了你。因为它是一个pretty共同的任务,这意味着多个控制器需要访问该功能,所以创建自己的 BaseController 所有控制器的派生,是必经之路去了。

The best way to handle this is by having a method on your controller which can build lists for you. As it's a pretty common task, that suggests multiple controllers would need access to that functionality, and so creating your own BaseController which all controllers derive from, is the way to go.

考虑到这一点,这里有一个 BaseController 与我写了建立一个通用的方法,任何的SelectList

With that in mind, here's a BaseController with a generic method I wrote to build any SelectList:

public class BaseController : Controller
{
    [NonAction]
    public SelectList BuildSelectList<TSource>(IEnumerable<TSource> source,
        Expression<Func<TSource, int>> valueKey, Expression<Func<TSource, string>> textKey,
        object selectedValue = null)
    {
        var selectedValueKey = ((MemberExpression)(MemberExpression)valueKey.Body).Member.Name;
        var selectedTextKey = ((MemberExpression)(MemberExpression)textKey.Body).Member.Name;

        return new SelectList(source, selectedValueKey, selectedTextKey, selectedValue);
    }
}

请注意标记方法使用的 NonActionAttribute 。这prevents被调用作为一个动作的方法。下面是如何使用这个简单的例子。

Note the use of the NonActionAttribute marking the method. This prevents the method being invoked as an action. Below is a simple example of how to use this.

public class StudentViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    [Display(Name = "Course")]
    public int CourseId { get; set; }
    public SelectList Courses { get; set; }
}

CourseId 重新presents所选课程。

CourseId represents the selected course.

public class Course
{
    public int Id { get; set; }
    public string Name { get; set; }
}

的HomeController

// Notice how we're deriving from BaseController
public class HomeController : BaseController
{
    public ActionResult Index()
    {
        var model = new StudentViewModel();
        model.Id = 1;
        model.Name = "John";
        model.Courses = BuildSelectList(this.courses,
                                        m => m.Id, m => m.Name);

        return View(model);
    }

    [HttpPost]
    public ActionResult Index(StudentViewModel model)
    {
        if (ModelState.IsValid)
        {
            return RedirectToAction("Success");
        }

        // The model wasn't valid, so repopulate the dropdown
        model.Courses = BuildSelectList(this.courses, m => m.Id,
                                        m => m.Name, model.CourseId);

        return View(model);
    }
}

您会然后显示像这样在您的视图下拉:

You'd then display the dropdown in your view like so:

@Html.DropDownListFor(m => m.CourseId, Model.Courses)

这篇关于传递数据用行动C#MVC查看的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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