2014-11-19 2 views
2

ASP.NET 용 소개 자습서를 통해 간단하게 CRUD 관리 응용 프로그램을 구현하는 방법을 알게되었습니다.일반 CRUD 컨트롤러 및 뷰

일반적인 목록/생성/업데이트/삭제 작업을 구현하기 위해 일반적으로 사용되는 패턴이 있습니까? 모든 모델에 대해 스캐 폴딩을 작성한 다음 추가, 편집 및 목록보기 및 컨트롤러를 모두 유지해야하는 것은 매우 지루한 것처럼 보입니다. 어떤 모델을 처리 할

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

: 그것은 훨씬 더 효율적이고 같은 일반적인 작업을 구현하는 적은 오류가 발생하기 쉬운 것입니다.

+1

이 게시물은 내가 뭘하려고하는지에 대한 좋은 토론을 가지고 있습니다. http://stackoverflow.com/questions/1124877/is-an-abstract-crud-controller-a-good-idea?rq=1 –

+0

감사합니다. 나는 다른 사람들이 다른 유스 케이스를 가지고 있다고 생각하며, 우리가 일반적인 솔루션이 우리에게 잘 작동한다는 것을 다른 플랫폼을 위해 구축 한 과거의 경험과 솔루션에서 알 수 있습니다. – pixelmike

답변

12

제가 작성한 관리 응용 프로그램에서 여러분이 말하는 것과 비슷한 점을 보았습니다. 기본적으로, 핵심은 제네릭을 사용하는 것입니다. 그냥 핵심 부품이 대신 구체적인 클래스의 일반 TEntity을 사용하고 있는지되는으로, 전체 재사용 가능한 컨트롤러 구조를 구축, 즉

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); 
    } 

    ... 
} 

: 즉, 같은 컨트롤러를 만들 수 있습니다. TEntityIEntity, class, new()으로 정의됩니다. 이것은 몇 가지 일을합니다. 첫째, class은 구체적인 유형으로 취급 할 수 있으며 new()은 유형이 추상적 인 클래스가 아닌 인스턴스화 될 수있는 유형이된다는 것을 의미합니다. IEntity은 모든 유형에 공통 분모가 있는지 확인하기 위해 애플리케이션에서 사용할 수있는 항목의 자리 표시 자일뿐입니다. 적어도 CRUD 스타일 응용 프로그램의 경우 편집 및 삭제 작업과 같은 항목에 대해 Id 또는 유사한 속성에 액세스하려면이 기능이 필요합니다. TEntityIEntity을 구현하면 IEntity에있는 모든 속성을 활용할 수 있습니다. 인터페이스 대신 콘크리트 유형을 사용하는 경우 class 부분을 생략 할 수 있습니다 (예 : where TEntity : Entity, new().

그런 다음, 이것을 사용하기 위해, 당신은 단지 AdminController<>에서 상속 새로운 컨트롤러를 정의하고 작업중인 유형을 지정 : 잠재적으로 당신이 당신의 개별 컨트롤러에 필요한 모든 수

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

을 . 또한 여기서 주목할 가치는 필자의 컨텍스트에 종속성 주입을 사용하도록 설정 한 것입니다. 생성자를 항상 다음과 같이 변경할 수 있습니다.

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

그러나 일반적으로 종속성 삽입을 사용하는 것이 좋습니다. 또한 여기에서 설명을 쉽게하기 위해 컨텍스트를 사용하지만 대개 서비스, 리포지토리 등을 대신 사용합니다.

마지막으로, CRUD 작업의 특정 부분을 사용자 정의해야하지만 전체적인 것은 아니더라도 항상 확장 점으로 메소드를 추가 할 수 있습니다.

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> 
     { 
      ... 
     }; 
    } 
} 

을, 당신의 후크가 당신의 기본 동작 메서드를 사용하면 전체 동작 자체를 재정의하지 않고 특정 기능 비트 만 변경하면됩니다.그것은 모두에 따라

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

:

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

: 그리고

당신은 또한 당신이 뭔가에 제네릭 클래스 정의를 확장 될 전망 모델 등이 포함이 더 걸릴 수 있습니다 귀하의 응용 프로그램이 필요로하는 것.

+0

감사합니다. 매우 도움이됩니다. – pixelmike

+0

thx 크리스, 몇 가지 다른 게시물의 좋은 확장,이 편리하게 보관하겠습니다 :-) –

+0

@ 크리스, 훌륭한 답변으로 저를 구해준 시간 동안 많은 맥주를 빚진 것입니다. 고마워. –