通用CRUD控制器和视图 [英] Generic CRUD controllers and views

查看:141
本文介绍了通用CRUD控制器和视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是经历了ASP.NET一些介绍教程和我有如何实现一个简单的CRUD管理应用一个体面的想法。

I'm just going through some intro tutorials for ASP.NET and I've got a decent idea of how to implement a simple CRUD admin app.

是否有任何常用的模式来实现泛型列表/创建/更新/删除操作?看来pretty乏味必须建立脚手架每一个模型,然后保持所有的添加,编辑和列表视图和控制器。这将是一个很多更高效,更不容易出错实现就像普通的动作:

Are there any commonly used patterns to implement generic List/Create/Update/Delete actions? It seems pretty tedious to have to build scaffolding for every model, and then to maintain all of the add, edit and list views and controllers. It would be a lot more efficient and less error-prone to implement generic actions like:

/List/Model
/Edit/Model/id
/Update/Model/id
/Delete/Model/id

这将处理任何模型。

推荐答案

我已经做了类似的事情,我想,你是在一个管理应用程序我建说什么。基本上,关键是使用泛型。换句话说,你创建了一个控制器:

I've done something similar, I think, to what you're talking about in an admin application I built. Basically, the key is to use generics. In other words, you create a controller like:

public abstract class AdminController<TEntity> : Controller
    where TEntity : IEntity, class, new()
{
    protected readonly ApplicationDbContext context;

    public virtual ActionResult Index()
    {
        var entities = context.Set<TEntity>()
        return View(entities);
    }

    public virtual ActionResult Create()
    {
        var entity = new TEntity();
        return View(entity);
    }

    [HttpPost]
    public virtual ActionResult Create(TEntity entity)
    {
        if (ModelState.IsValid)
        {
            context.Set<TEntity>().Add(entity);
            context.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(entity);
    }

    ...
}

在换句话说,你只要建立一个完整的可重复使用的控制器结构,关键部位在于你使用普通的 TEntity ,而不是一个具体的类。请注意, TEntity 定义为 IEntity,阶级,新的()。这做了几件事情。首先,,您可以把它当作一个具体类型和新()意味着该类型将是东西,可以被实例化,而不是像一个抽象类。 IEntity 就是任何你可能会使用你的应用程序,以确保所有类型有一些共同点的占位符。最起码的CRUD风格的应用程序,您需要这获得了编号或类似性质的东西像你的编辑和删除操作。话说 TEntity 工具 IEntity 让你使用的 IEntity 。如果您在这里使用的具体类型,而不是一个接口,你可以离开关部分,例如其中TEntity:实体,新的()

In other words, you just build an entire reusable controller structure, with the key parts being that you're using the generic TEntity instead of a concrete class. Notice that TEntity is defined as IEntity, class, new(). This does a few things. First, class allows you to treat it as a concrete type and new() means that the type will be something that can be instantiated, rather than something like an abstract class. IEntity is just a placeholder for whatever you may be using in your application to ensure all the types have some common denominator. At the very least for a CRUD-style application, you'll need this to gain access to an Id or similar property for things like your edit and delete actions. Saying that TEntity implements IEntity lets you utilize any properties on IEntity. If you use a concrete type here instead of an interface, you can leave off the class part, e.g. where TEntity : Entity, new().

然后,为了使用它,你只定义了一个新的控制器,从 AdminController&LT继承;&GT; ,并指定您正在使用的类型:

Then, in order to use this, you just define a new controller that inherits from AdminController<> and specify the type you're working with:

public class WidgetController : AdminController<Widget>
{
    public WidgetController(ApplicationDbContext context)
    {
        this.context = context;
    }
}

这可能是潜在的,所有你需要为你的个人控制器。此外,值得一提的是在这里,我已经设置此采用的依赖注入上下文。你总是可以构造函数更改为类似:

That could be potentially all you need for your individual controllers. Also, worth noting here is that I've set this up to employ dependency injection for your context. You could always change your constructor to something like:

public WidgetController()
{
    this.context = new ApplicationDbContext();
}

不过,我建议你考虑使用依赖注入,一般。另外,我使用的情况下直接在这里为了便于解释,但通常你会使用服务,信息库等在这里吧。

But, I recommend you do look into using dependency injection, in general. Also, I'm using the context directly here for ease of explanation, but usually you'd be employing services, repositories, etc. here instead.

最后,如果你发现你需要定制一个CRUD操作的某些部分,但不一定是整个事情,你可以随时添加方法为扩展点。例如,假设你需要填充一个选择列表中一个特定的实体,你可以这样做:

Finally, if you find you need to customize certain parts of a CRUD action, but not necessarily the whole thing, you can always add methods as extension points. For example, let's say you needed to populate a select list for one particular entity, you might do something like:

public abstract class AdminController<TEntity> : Controller
    where TEntity : IEntity, class, new()
{
    ...

    public virtual ActionResult Create()
    {
        var entity = new TEntity();
        BeforeReturnView();
        return View(entity);
    }

    ...

    protected virtual void BeforeReturnView()
    {
    }

    ...

和则:

public class WidgetController : AdminController<Widget>
{
    ...

    protected override void BeforeReturnView()
    {
        ViewBag.MySelectList = new List<SelectListItem>
        {
            ...
        };
    }
}

在换句话说,你有你的基地的操作方法一个钩子,您可以覆盖只需更改,而不必重写整个动作本身的功能,尤其是位。

In other words, you have a hook in your base action method that you override to just change that particular bit of functionality instead of having to override the whole action itself.

您也可以借此更远包括像视图模型,在那里你可以扩大你的泛型类定义是这样的:

You can also take this farther to include things like view models, where you might expand your generic class definition to something like:

 public abstract class AdminController<TEntity, TEntityViewModel, TEntityCreateViewModel, TEntityUpdateViewModel>
     where TEntity : IEntity, class, new()
     where TEntityViewModel : class, new()
     ...

和则:

public class WidgetController : AdminController<Widget, WidgetViewModel, WidgetCreateViewModel, WidgetUpdateViewModel>
{
    ...
}

这一切都取决于你的应用程序需要的东西。

It all depends on what your application needs.

这篇关于通用CRUD控制器和视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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