Asp MVC 解决方案结构

Asp MVC solution structure

我刚刚开始使用 MVC,并选择让我的解决方案为数据库交互保留单独的项目,为 UI 保留一个项目(希望这是一种可接受的工作方式)。 UI 引用了 BL,但是 BL 没有引用 UI。因此,为了将值传递给 BL,我必须将参数设置为 dynamic(下面的示例),应该避免这种情况吗?如果是,为什么?(除了缺乏智能感知)。

public class MyController : Controller
{
    [HttpPost]
    public ActionResult MyAction(MyActionViewModel vm)
    {
        if (!ModelState.IsValid)
        {
            return View(vm);
        }

        //pass formCollection to model to do stuff with
        int isSuccessful = ModelName.Insert(vm);
        return RedirectToAction(....);
    }
}

public partial class ModelName
{
    public static int Insert(dynamic theVm)
    {
        using (ModelEntities ctx = new ModelEntities ())
        {
            ModelName mn= new ModelName();
            mn.AddressLineOne = theVm.AddressLineOne;
            mn.AddressLineTwo = theVm.AddressLineTwo;

            ctx.TheTargetedEntity.Add(mn);
            ctx.SaveChanges();
            return mn.id;
        }
    }
}

一位同事建议我应该做一个额外的项目,同时引用 BL 和 UI,这样我就可以强类型化我传递的参数(并尽可能避免弱类型化) .我的问题是,在这种情况下,它似乎在解决方案中引入了不必要的元素。

我是不是以过于简单化的方式看待这个问题,或者是建议使问题过于复杂,还是我们都完全遗漏了一些东西(我们都是 MVC 的新手,来自 Web 表单,而且网站会小到中型网站)。

你的BL项目应该对UI一无所知,没错。我认为使用动态不是一个好主意。您应该将 ViewModel 对象转换为 BL 对象。您可以使用 AutoMapper 来完成 http://automapper.org/

我认为与其将动态传递给 BLL,不如为您的模型创建一个项目并将您的模型放在那里,这样模型库就可以在 UI 和 BLL 之间共享,而不会违反任何规则并且无需使 BLL 依赖于 UI.

使用动态你会错过的不是 intellisense,而是工作类型。

项目结构将是:

  • 模型项目(独立,仅包含模型)
  • BLL 项目(参考模型,包含数据访问和业务逻辑)
  • UI 项目(有 BLL 参考,有模型参考,包含 ViewModels、Controllers、Views)

从技术上讲,模型项目可以在不违反规则的情况下合并到 BLL 中,但是将它们放在单独的程序集中有其好处。

您应该在时间、预算、项目规模等之间进行权衡,以做出正确的决定。但是对于开始,这 3 层就足够了(虽然您可以将主题减少到 2 层)。

我认为您应该放弃使用 dynamic 并使用更严格的定义参数。首先,当其他人阅读您的代码和编写单元测试时,它会让您的意图更加清晰。

如果您知道插入的是哪个实体,则可以将其作为参数显式传递。如果您不知道插入的是哪个实体,则可以传递每个实体继承的基础 class 或接口。此 class 或接口将定义所有使用它的实体共有的属性,例如

public class BaseEntity
{
    public int Id {get; set;}
}

public partial class ModelName : BaseEntity
{ 
    //Properties unique to ModelName
}

您应该在模型之外编写映射代码。如果你想让你的控制器变薄,你可以创建一个单独的中间层来做到这一点。

考虑创建一个单独的 class 来容纳您的实体操作,而不是使用静态函数。我觉得在这里使用静态方法违反了 OO 设计。创建这个单独的 class 不需要您编写比现有代码更多的代码,但它会重新排列您的代码以使其看起来更清晰。

public class BusinessService()
{
    public int Insert(ModelName model)
    {
        ctx.TheTargetedEntity.Add(model);
        ctx.SaveChanges();
        return model.id;
    }
}

public class PresentationService()
{
    public int Insert(MyActionViewModel theVm)
    {
        ModelName mn = new ModelName();
        mn.AddressLineOne = theVm.AddressLineOne;
        mn.AddressLineTwo = theVm.AddressLineTwo;
        return businessService.Insert(mn);
    }
}

我将按如下方式添加项目引用: 控制器 -> PresentationService -> BusinessService -> DB