【问题标题】:ASP.NET MVC 2 - How do I properly switch views based on model context?ASP.NET MVC 2 - 如何根据模型上下文正确切换视图?
【发布时间】:2011-04-08 18:53:12
【问题描述】:

我正在整理我的第一个 MVC 应用程序,并且有一个关于如何正确实现我的目标的问题。这是我正在尝试的...

我的应用程序中的一个区域显示了一批数据的列表,即Batch 对象的列表。对于每个Batch,用户可以选择处理其数据。该处理由一组步骤组成,我将以类似向导的视图链向用户展示这些步骤。

每个Batch 都有一个类型。 L 类型的批次 A 可能包含 X 的记录,而类型 M 的批次 B 可能包含 Y 的记录。向导中的步骤将根据批次类型略有变化。我不想做的是这个(显然是糟糕的代码,只是为了说明):

流程控制器

public ActionResult StepOne(int id)
{
    var batch = BatchRepository.Batch.SelectById(id);
    var records = BatchRepository.Data.SelectForBatch(batch);

    switch (batch.BatchType)
    {
        case "X":
            return View("TypeXStepOne", records);
        case "Y":
            return View("TypeYStepOne", records);
        default:
            return View();
    }

}

public ActionResult StepTwo(int id)
{
    var batch = BatchRepository.Batch.SelectById(id);
    var records = BatchRepository.Data.SelectForBatch(batch);

    switch (batch.BatchType)
    {
        case "X":
            return View("TypeXStepTwo", records);
        case "Y":
            return View("TypeYStepTwo", records);
        default:
            return View();
    }

}

...

等等。这似乎是一种不好的做法,因为我的向导可能是 4 或 5 步,而我目前有三种不同的批处理类型,这些操作中的代码量变得难以维护。

在管理这方面,MVC 能为我做些什么?例如,如果引入了第四种类型,我想尽量减少所需的工作量。

我知道我可能会有:

  • 每个批次类型的局部视图 并进入向导,有 确实没有办法解决这个问题,尽管可能会分享一些部分观点。

那么,每个批次类型都有一个专用控制器会更好吗?我想我可以做这样的事情,其中​​批处理类型成为控制器名称。

批处理控制器

public ActionResult Process(int id)
{
    var batch = BatchRepository.Batch.SelectById(id);
    return RedirectToAction("StepOne", batch.BatchType, new { id = batch.Id });
}

但这取决于与控制器名称匹配的批处理类型名称,我也不一定喜欢这样。 更新:或者,最坏的情况是,我在这里有一个包含三种批处理类型的 switch 语句,然后我可以转发到相应的控制器。

所以...想法!我需要他们。而且我还没有到这一步,我不能开始新的东西,我只是作为一个 MVC 新手在我的脑海中抛出一些想法。 MVC 必须具有允许基于上下文进行动态视图切换的功能,无论是通过花哨的路由技术还是“ViewFactory”或其他一些技巧。

任何反馈都将不胜感激!

对于任何想知道的人,我被困在 .NET 3.5 和 IIS6 上,这就是为什么我回到 MVC 2 而不是 3。

UDPATE

这就是我现在正在滚动的内容。我将 BatchController 分成多个控制器——每个批次类型一个。由于它们大多相同,我创建了一个抽象的WizardController,其中包含这些方法:

public abstract ActionResult Step(int batchId, int stepNumber);

protected ViewResult ViewStep(int stepNumber, object model)
{
    return View(string.Format("Process\Step{0}", stepNumber), model);
}

在我的派生控制器中,类似:

public override ActionResult Step(int batchId, int stepNumber)
{
    var data = BatchRepository.BatchType.SelectByBatchId(batchId);

    return ViewStep(stepNumber, data);
}

它很快而且看起来很脏,但在我学到更好的东西之前......谢谢!

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-2 asp.net-mvc-routing


    【解决方案1】:

    约定优于配置(新的硬编码),如下所示:

    public ActionResult Step(int stepNo, int id)
    {
        var batch = BatchRepository.Batch.SelectById(id);
        var records = BatchRepository.Data.SelectForBatch(batch);
        return View("Type"+batch.BatchType+"Step"+stepNo, records);    
    }
    

    【讨论】:

    • 这或多或少是我选择的路线。我更新了我的帖子以展示我的所作所为。
    【解决方案2】:

    您不需要 switch 语句。在适当的位置创建一个 DisplayTemplates 或 EditorTempaltes 文件夹,例如 Views/Shared/ 并创建 YourRecordType.cshtml 文件,然后将您的 return 语句更改为仅返回模型。例如

    -View
     -Shared
      -DisplayTemplates
       -MyRecordTypeA.cshtml
       -MyRecordTypeB.cshtml
    
    return View(records)
    

    希望对您有所帮助。

    【讨论】:

    • -1:这不是 Razor 和 MVC 3 的特性吗?我正在使用 MVC 2。
    • 实际上,这在这种情况下不起作用,因为他返回的是相同的模型类型。他需要将模型包装在另一个模型中(“ModelWithBatchTypeA”等),然后为这些模型创建模板视图和编辑器。但是,switch 方法比那个例子效果更好。
    • @cory 不,它是 MVC2 bradwilson.typepad.com/blog/2009/10/… 的一部分。 @xixonia 我可能误解了,但他确实提到每批都是自己的类型。
    • 哦,对不起 - 除非问题被编辑,否则它不会让我撤消我的反对票。
    • @cory 不用担心,如果您返回不同的模型,模板解决方案将起作用。我发布的链接非常详细,应该为您指明正确的方向。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-09
    • 2016-01-30
    相关资源
    最近更新 更多