2013-11-25 24 views
0

我正在构建一个MVC 5应用程序,用于处理员工的日志记录时间等。我已经有一个完整的CRUD控制器,可以处理员工记录,并且我有一个时间表控制器用于输入员工时间。如何从多个地方使用MVC控制器

我想添加快捷方式到Timesheets/Index视图来访问Employees模块,而无需通过Admin/Index视图。我还想直接从下属视图中的员工编辑方法访问Timesheets/Index。

本着DRY的精神,我是否可以重用员工控制器逻辑并仍然回到我从哪里来,或者是否需要复制员工逻辑以用不同的操作链接调用不同的视图? (我知道我可以通过使用部分模板重用视图代码的一部分,但这并不够远)。

确定没有回答我没有做很好的解释我想要做的事情。下面是雇员控制器代码的一部分:

public partial class EmployeesController : Controller 
{ 
    // 
    // GET: /Employees/ 

    public virtual ActionResult Index(int? page) 
    { 
     const int pageSize = 15; 

     var masterDataProxy = MasterDataChannelFactory.OpenChannel(); 
     var employees = masterDataProxy.GetPagedEmployees((page ?? 0) * pageSize, pageSize); 
     masterDataProxy.CloseChannel(); 

     ViewBag.HasPrevious = employees.HasPrevious; 
     ViewBag.HasMore = employees.HasNext; 
     ViewBag.CurrentPage = (page ?? 0); 

     return View(employees.Entities); 
    } 

    // 
    // GET: Employees/Edit/{id} 

    //[Authorize(Roles = "Admin")] 
    public virtual ActionResult Edit(int id) 
    { 
     var masterDataProxy = MasterDataChannelFactory.OpenChannel(); 
     var employee = masterDataProxy.GetEmployee(id); 
     masterDataProxy.CloseChannel(); 

     return View(employee); 
    } 

    // 
    // POST: Employees/Edit/{id} 

    [AcceptVerbs(HttpVerbs.Post), /*Authorize(Roles = "Admin")*/] 
    public virtual ActionResult Edit(int id, FormCollection formValues) 
    { 
     var masterDataProxy = MasterDataChannelFactory.OpenChannel(); 
     var employee = masterDataProxy.GetEmployee(id); 
     masterDataProxy.CloseChannel(); 

     if (null == employee) 
     { 
      return View(Views.NotFound); 
     } 

     try 
     { 
      UpdateModel(employee, formValues.ToValueProvider()); 

      var adminProxy = AdminChannelFactory.OpenChannel(); 
      adminProxy.AddUpdateEmployee(employee); 
      adminProxy.CloseChannel(); 

      return RedirectToAction(Actions.Index()); 
     } 
     catch (Exception ex) 
     { 
      ModelState.AddModelError("Employee", ex.Message); 

      return View(employee); 
     } 
    } 
... 
} 

这里是管理索引页面视图的一部分:

@{ 
    ViewBag.Title = "Master Data Admin"; 
} 

<h2>Master Data</h2> 

<ul> 
    <li>@Html.ActionLink("Accounts", MVC.Account.Actions.Index())</li> 
    <li>@Html.ActionLink("Employees", MVC.Employees.Actions.Index())</li> 
</ul> 

然后,我有一个时间表/索引视图,我想另一个ActionLink的增加雇员。我的问题是我怎么写这个,所以我可以从任一视图(Admin/Index或Timesheets/Index)调用Employees Controller,更新服务上的Employees,然后返回到我被调用的地方?

看来这应该是一个解决的问题,但我找不到任何接近我想要做的事情。也许我需要重述这个问题?我shoudl补充我是一个相对的新手MVC和网络编程一般...

在此先感谢您的任何帮助或指导。

戴夫

+0

一些基本的代码在这里真的很有用。伪代码,如果需要的话。 –

+0

发布员工控制器逻辑,也许逻辑应该在一个共同的类?控制器不应该有太多的代码。 – christiandev

+0

可能将逻辑从您的控制器中取出并放入某种服务类别中。然后,您可以从任何需要它的控制器调用该逻辑,并且控制器可以以任何合理的方式呈现它。 –

回答

0

所有这些东西是伟大的,但我想,我问的是如此简单,它只是假设我已经知道了。我可以肯定地看到存​​储库和业务层的优势,并将“做正确的事情”并将数据访问从控制器中分离出来。但是,这并不能回答我的问题。

我需要做的是拿编辑屏幕的肉,并创建一个局部视图。然后,我需要为每个控制器调用创建一个单独的视图,其中包含正确的链接以让我回到开始的位置。

查看从管理员/员工/编辑叫:

@model HawkTimeModel.Employee 

@{ 
    ViewBag.Title = "Edit Employee"; 
} 

<h2>Edit</h2> 

@{ Html.RenderPartial(MVC.Employees.Views._EmployeeForm); } 

<p> 
    @Html.ActionLink("Back to List", MVC.Employees.Actions.Index()) 
</p> 

查看从时间表/ EditEmployee:

@model HawkTimeModel.Employee 

@{ 
    ViewBag.Title = "Edit Employee"; 
} 

<h2>Edit</h2> 

@{ Html.RenderPartial(MVC.Employees.Views._EmployeeForm); } 

<p> 
    @Html.ActionLink("Back to Timesheet Overview", MVC.Timesheets.Actions.Index()) 
</p> 

就是这样, “缺失环节”。现在看,我不明白我是如何忽略这么简单的事情的。

感谢您的意见,但我的应用会因您的反馈而变得更好!

戴夫

2

如果我理解正确的话,你要使用的Employee操作方法,而不局限于Employee意见。

我会在您的应用程序(可能在一个单独的项目中)中创建一个处理Employee逻辑的服务层。然后从您的Employee控制器和您的Timesheets控制器,您可以调用EmployeeService服务。

这样您的业务逻辑(EmployeeService)与您的演示逻辑(EmployeeTimesheets控制器和相关视图)是分开的。因此,您的控制器可以使用存储在EmployeeService中的逻辑,并仍然使用自己的视图进行演示。

这实际上变成了2层设计。如果你的应用程序足够复杂,你甚至可以将你的数据访问逻辑分成单独的层 - 有效地使你的应用程序3层。

示例结构可能如下所示。

Presentation Layer Project (PL) 
     Controllers/ 
      EmployeeController 
      TimesheetsController 
     Views/ 
      Employee/ 
      Timesheets/ 
     ... 

    Business Logic Layer Project (BLL) 
     ViewModels/ 
     Services/ 
     ... 

    Data Access Layer Project (DAL) 
     Models/ 
     Repositories/ 
     ... 

(这里PL将引用BLL和BLL引用DAL项目)。

这可能会给出更多的信息:https://softwareengineering.stackexchange.com/questions/135724/separating-data-access-in-asp-net-mvc

+1

到底是怎么做到的。控制器只是业务逻辑和用户界面之间的薄弱环节。起初,将业务逻辑放在控制器中似乎很自然,但是当你开始尝试共享业务逻辑时,最终将其重构为另一层。最终,这变得非常常见,您只需通过创建和/或查找可重用的服务类来处理后端内容,就可以自动开始每个新的控制器实现。 – AaronLS

+0

这实际上是我如何做到的,但我不确定这是如何回答我的问题的。采用这种方法,我仍然需要单独的视图来访问不同的地方?真的,我需要弄清楚的是如何获得“回归”链接,以便始终让我回到我来自的地方。 – DaveN59

+1

如果你只想让你的链接返回到调用页面,你可以在'ViewBag'变量的'Shared \ _Layout'视图中设置它,例如,它跟踪你的位置。用它来建立你的链接。但是......然后回到我被叫去的地方 - 你的控制器不会为你做这件事。 – erdinger

0

我的同事提出了另一种解决方案。修改模型,使其具有一个变量,用于定义视图的调用位置,并使用该变量来确定页面底部的“返回链接”。然后,主索引视图看起来是这样的:

@using WebReporter.Models 

@{ Html.RenderPartial(MVC.Employees.Views._IndexPartial); } 

@if (Model.HomePage == HomePage.Timesheets) 
{ 
    <p> 
     @Html.ActionLink("Back to Timesheet Overview", MVC.TimeSheets.Index()) 
    </p> 
} 

......,被称为像这样:

public virtual ActionResult Index(HomePage homePage, int? page) 
    { 
     return View(_masterDataService.GetPagedEmployees(homePage, page)); 
    } 

我原本内置的员工意见和控制器的第二个副本,但它似乎违反干的原则,所以我正在尝试这一点。

我不敢相信这很难解释。我不能成为唯一一个想重复使用整个Controller + Views来自多个地方的人,所以我必须对它解释不好......

感谢您的建议,尽管如此,我的代码会更适合您输入!

相关问题