문제

이 질문, 처럼,그것은 보인 그것이 의미가 있는 컨트롤러 만들기 뷰 모델 는 더 정확하게 반영하는 모델의 보기를 표시하려고하지만,저는 호기심의 일부에 대해 규정(나는 새로운 MVC 패턴,이미 하지 않은 경우 명백한).

기본적으로,나는 다음과 같은 질문:

  1. 나는 일반적으로 좋아하는 하나의 클래스/파일입니다.이 말이로 뷰 모델 는 경우에 그것은 단지 만들어 손에서 데이터를 컨트롤러를 볼 수 있을까요?
  2. 는 경우 뷰 모델 에 속하지 않는 자신의 파일을 사용하여 디렉토리/프로젝트 구조를 유지하는 것을 별도로,어디가 뷰 모델 파일에 속하는가?에 컨트롤러 디렉토리?

는 기본적으로 그것이다.수있는 몇 가지 질문을 더 올라오고 있지만,이는 나를 괴롭히는 마지막 시간,그리고 나는 할 수 있는 것을 찾을 수 있는 일관된 지침이다.

편집: 샘플 NerdDinner 램 에 CodePlex,그것은 다음과 같 ViewModels 의 컨트롤러, 지만,그것은 여전히 나에게 불편지에서 자신의 파일이 있습니다.

도움이 되었습니까?

해결책

내가 만드는 무엇이"뷰 모델"각각 보기입니다.내가 그들에게 이라는 폴더에 ViewModels 내 MVC 웹 프로젝트입니다.나는 그들의 이름을 후 컨트롤러와 작업(또는 뷰)그들은 나타냅니다.그래서 필요한 경우 통과 데이터를 등록에서 볼 수원 컨트롤러를 만들 MembershipSignUpViewModel.cs 클래스고에 넣어 ViewModels 폴더에 있습니다.

그때 나는 추가 필요성과 방법을 촉진하는 데이터의 전송을 컨트롤러에서 보기입니다.사용 Automapper 에서 얻을 내 뷰 모델을 도메인 모델에 다시 다시 필요한 경우입니다.

이것은 또한 복합 ViewModels 는 속성이 포함되어 있는 유형의 다른 ViewModels.예를 들어 있는 경우 5 위젯에 인덱스 페이지에서 회원 자격 컨트롤러를 만든 시점에 대한 각 부분보기-당신은 어떻게 통과 데이터 인덱스에서 작업하는 부분?을 추가 제공하 MembershipIndexViewModel 의 유형 MyPartialViewModel 및 렌더링할 때는 부분을 전달 모델입니다.MyPartialViewModel.

이 방법을 조정할 수 있는 부분 뷰 모델 속성을 변경하지 않고 인덱스보기 모든.그것은 여전히 그냥 전달 모델입니다.MyPartialViewModel 그래서 거의 더 적은에 대한 정보를 제공합니다.을 통해 이동해야의 전체 체인 부분이 뭔가를 해결할 때 모든 당신이 하고 있는 속성을 추가하는 부분 뷰 모델.

나는 것입니다 또한 추가 네임스페이스"하위.웹.ViewModels"니다.구성할 수 있도록을 참조에서 그들을 보기를 추가하지 않고 명시적인 수입 문서 각각 보기입니다.그것은 작은 청소기입니다.

다른 팁

카테고리별로 클래스를 분리하는 것은 (컨트롤러, 뷰 모델, 필터 등) 말도 안됩니다.

웹 사이트의 홈 섹션 (/)에 대한 코드를 작성하려면 Home이라는 폴더를 만들고 HomeController, IndexViewModel, AboutViewModel 등 및 Home Actions에서 사용하는 모든 관련 클래스를 넣으십시오.

ApplicationController와 같은 클래스를 공유 한 경우 프로젝트의 루트에 넣을 수 있습니다.

관련된 것들 (HomeController, IndexViewModel)과 전혀 관계가없는 물건을 유지하는 이유는 무엇입니까 (HomeController, AccounTontroller)?


나는 a 블로그 게시물 이 주제에 대해.

응용 프로그램 클래스를 "Core"(또는 별도의 클래스 라이브러리)라는 하위 폴더에 보관하고 키그 샘플 애플리케이션이지만 약간의 변경 사항이 약간 변경되어 응용 프로그램이 더 건조 해집니다.

/core/viewData/에서 baseViewData 클래스를 만듭니다. 공통 사이트 넓은 속성을 저장합니다.

이 후에도 동일한 폴더에서 ViewData 클래스를 모두 만들어 BaseViewData에서 파생되고 특정 속성이 있습니다.

그런 다음 모든 컨트롤러가 파생 한 ApplicationController를 만듭니다. ApplicationController에는 다음과 같이 일반적인 getViewData 메소드가 있습니다.

protected T GetViewData<T>() where T : BaseViewData, new()
    {
        var viewData = new T
        {
           Property1 = "value1",
           Property2 = this.Method() // in the ApplicationController
        };
        return viewData;
    }

마지막으로 컨트롤러 작업에서 ViewData 모델을 빌드하기 위해 다음을 수행합니다.

public ActionResult Index(int? id)
    {
        var viewData = this.GetViewData<PageViewData>();
        viewData.Page = this.DataContext.getPage(id); // ApplicationController
        ViewData.Model = viewData;
        return View();
    }

나는 이것이 정말로 잘 작동한다고 생각하고 그것은 당신의 견해를 깔끔하게 유지하고 컨트롤러를 마른 상태로 유지합니다.

ViewModel 클래스는 클래스의 인스턴스로 표시되는 여러 데이터를 캡슐화하여 시야에 전달할 수있는 하나의 관리하기 쉬운 객체로 캡슐화 할 수 있습니다.

자체 디렉토리에 자신의 파일에 ViewModel 클래스를 갖는 것이 합리적입니다. 내 프로젝트에는 ViewModels라는 모델 폴더의 하위 폴더가 있습니다. 그것이 내 뷰 모델 (예 : ProductViewModel.cs) 라이브.

프로젝트가 크고 뷰 모델 (데이터 전송 개체)이 많으면 모델을 보관할 수있는 좋은 장소는 없습니다. 또한 사이트 프로젝트의 별도 폴더에 보관할 수 있습니다. 예를 들어, 옥사 사이드 그것들은 다양한 종류의 다양한 클래스를 포함하는 옥사 사이트 프로젝트에 배치됩니다. 옥사 사이트의 컨트롤러는 별도의 프로젝트로 이동되며 견해는 별도의 프로젝트에 있습니다.
~ 안에 Codecampserver ViewModels는 *형식으로 지정되었으며 모델 폴더의 UI 프로젝트에 배치됩니다.
~ 안에 mvcpress 데이터베이스에 배치 된 프로젝트는 데이터베이스와 함께 작동하는 모든 코드와 조금 더 포함되어 있습니다 (그러나이 접근법을 권장하지는 않았지만 샘플을위한 것입니다).
따라서 많은 관점이 있음을 알 수 있습니다. 나는 보통 사이트 프로젝트에 내 뷰 모델 (DTO 객체)을 유지합니다. 그러나 10 개 이상의 모델이 있으면 분리 된 어셈블리로 옮기는 것을 선호합니다. 일반적 으로이 경우 컨트롤러를 분리하여 어셈블리를 분리합니다.
또 다른 질문은 모든 데이터를 모델에서 뷰 모델로 쉽게 매핑하는 방법입니다. 나는 보는 것이 좋습니다 automapper 도서관. 나는 그것을 매우 좋아합니다. 그것은 나를 위해 모든 더러운 일을합니다.
그리고 나는 또한 보는 것이 좋습니다 SharparChitecture 프로젝트. 그것은 프로젝트를위한 아주 좋은 아키텍처를 제공하며 멋진 프레임 워크와 지침과 훌륭한 커뮤니티가 많이 포함되어 있습니다.

모범 사례의 코드 스 니펫은 다음과 같습니다.

    public class UserController : Controller
    {
        private readonly IUserService userService;
        private readonly IBuilder<User, UserCreateInput> createBuilder;
        private readonly IBuilder<User, UserEditInput> editBuilder;

        public UserController(IUserService userService, IBuilder<User, UserCreateInput> createBuilder, IBuilder<User, UserEditInput> editBuilder)
        {
            this.userService = userService;
            this.editBuilder = editBuilder;
            this.createBuilder = createBuilder;
        }

        public ActionResult Index(int? page)
        {
            return View(userService.GetPage(page ?? 1, 5));
        }

        public ActionResult Create()
        {
            return View(createBuilder.BuildInput(new User()));
        }

        [HttpPost]
        public ActionResult Create(UserCreateInput input)
        {
            if (input.Roles == null) ModelState.AddModelError("roles", "selectati macar un rol");

            if (!ModelState.IsValid)
                return View(createBuilder.RebuildInput(input));

            userService.Create(createBuilder.BuilEntity(input));
            return RedirectToAction("Index");
        }

        public ActionResult Edit(long id)
        {
            return View(editBuilder.BuildInput(userService.GetFull(id)));
        }

        [HttpPost]
        public ActionResult Edit(UserEditInput input)
        {           
            if (!ModelState.IsValid)
                return View(editBuilder.RebuildInput(input));

            userService.Save(editBuilder.BuilEntity(input));
            return RedirectToAction("Index");
        }
}

우리는 모든 뷰 모델을 모델 폴더에 던져 넣습니다 (모든 비즈니스 로직은 별도의 Servicelayer 프로젝트에 있습니다).

개인적으로 ViewModel이 사소한 일이라면 별도의 클래스를 사용하는지 제안합니다.

하나 이상의보기 모델이 있다면 최소한 디렉토리에서 파티션하는 것이 합리적이라고 제안합니다. 보기 모델이 나중에 공유되면 디렉토리에 암시 된 이름 공간은 새 어셈블리로 쉽게 이동할 수있게합니다.

우리의 경우 우리는보기와 분리 된 프로젝트의 컨트롤러와 함께 모델을 가지고 있습니다.

경험상, 우리는 ViewData [ "..."] 물건의 대부분을 뷰 모델로 이동시키고 피하려고 노력했습니다.

ViewModel은 빵 부스러기 및 제목을 그리는 페이지의 목록 또는 헤더 정보에 대한 Pagination 정보와 같은 몇 가지 일반적인 속성을 보유합니다. 현재 기본 클래스는 내 의견으로는 너무 많은 정보를 보유하고 있으며 기본보기 모델에서 페이지의 99%에 가장 기본적이고 필요한 정보를 세 조각으로 나눌 수 있습니다. 해당 시나리오에 대한 특정 데이터를 보유하고 기본에서 상속하는 양식의 경우.

마지막으로, 우리는 특정 정보를 처리하기 위해 각 엔티티의 뷰 모델을 구현합니다.

컨트롤러의 코드 :

    [HttpGet]
        public ActionResult EntryEdit(int? entryId)
        {
            ViewData["BodyClass"] = "page-entryEdit";
            EntryEditViewModel viewMode = new EntryEditViewModel(entryId);
            return View(viewMode);
        }

    [HttpPost]
    public ActionResult EntryEdit(Entry entry)
    {
        ViewData["BodyClass"] = "page-entryEdit";            

        #region save

        if (ModelState.IsValid)
        {
            if (EntryManager.Update(entry) == 1)
            {
                return RedirectToAction("EntryEditSuccess", "Dictionary");
            }
            else
            {
                return RedirectToAction("EntryEditFailed", "Dictionary");
            }
        }
        else
        {
            EntryEditViewModel viewModel = new EntryEditViewModel(entry);
            return View(viewModel);
        }

        #endregion
    }

뷰 모델의 코드 :

public class EntryEditViewModel
    {
        #region Private Variables for Properties

        private Entry _entry = new Entry();
        private StatusList _statusList = new StatusList();        

        #endregion

        #region Public Properties

        public Entry Entry
        {
            get { return _entry; }
            set { _entry = value; }
        }

        public StatusList StatusList
        {
            get { return _statusList; }
        }

        #endregion

        #region constructor(s)

        /// <summary>
        /// for Get action
        /// </summary>
        /// <param name="entryId"></param>
        public EntryEditViewModel(int? entryId)
        {
            this.Entry = EntryManager.GetDetail(entryId.Value);                 
        }

        /// <summary>
        /// for Post action
        /// </summary>
        /// <param name="entry"></param>
        public EntryEditViewModel(Entry entry)
        {
            this.Entry = entry;
        }

        #endregion       
    }

프로젝트 :

  • DevJet.web (ASP.NET MVC 웹 프로젝트)

  • DevJet.web.app.Dictionary (Seperate Class Library 프로젝트)

    이 프로젝트에서 Dal, Bll, Bo, VM (보기 모델 용 폴더)과 같은 일부 폴더를 만들었습니다.

조작 및 상황 데이터와 같이 일반적으로 필요한 속성을 가진보기 모델 기본 클래스를 만듭니다. 현재 사용자 데이터 및 역할을 넣을 수도 있습니다.

class ViewModelBase 
{
  public bool HasError {get;set;} 
  public string ErrorMessage {get;set;}
  public List<string> UserRoles{get;set;}
}

기본 컨트롤러 클래스에는 PopulateViewModelBase ()와 같은 메소드가 있습니다.이 메소드는 상황에 맞는 데이터 및 사용자 역할을 작성합니다. HASERROR 및 ERRORMESSAGE는 Service/DB에서 데이터를 가져 오는 동안 예외가있는 경우 이러한 속성을 설정합니다. 오류를 보여주기 위해 이러한 특성을 바인딩하십시오. 사용자 역할을 사용하여 역할을 기반으로 시야에 숨은 부분을 표시 할 수 있습니다.

다른 GET 동작으로보기 모델을 채우려면 초록 메소드 FillModel을 사용하여 기본 컨트롤러를 사용하여 일관성을 유지할 수 있습니다.

class BaseController :BaseController 
{
   public PopulateViewModelBase(ViewModelBase model) 
{
   //fill up common data. 
}
abstract ViewModelBase FillModel();
}

컨트롤러에서

class MyController :Controller 
{

 public ActionResult Index() 
{
   return View(FillModel()); 
}

ViewModelBase FillModel() 
{ 
    ViewModelBase  model=;
    string currentAction = HttpContext.Current.Request.RequestContext.RouteData.Values["action"].ToString(); 
 try 
{ 
   switch(currentAction) 
{  
   case "Index": 
   model= GetCustomerData(); 
   break;
   // fill model logic for other actions 
}
}
catch(Exception ex) 
{
   model.HasError=true;
   model.ErrorMessage=ex.Message;
}
//fill common properties 
base.PopulateViewModelBase(model);
return model;
}
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top