문제

데이터 액세스에 nhibernate를 사용하는 ASP.NET MVC 2 RC 응용 프로그램에서 모델 바인딩에 문제가 있습니다. 우리는 Ruby on Rails Way로 애플리케이션을 구축하려고 노력하고 있으며 도메인 엔티티가 데이터베이스에서 뷰까지 사용되는 매우 간단한 아키텍처를 가지고 있습니다.

응용 프로그램에는 다음 두 클래스로 설명 할 수있는 몇 가지 도메인 엔티티가 있습니다.

public class Product {
    ...

    public Category Category { get; set; }      
}

public class Category {
    public int Id { get; set; }
    public string Name { get; set; }
}

편집 양식을 렌더링하는 관점에서 드롭 다운 목록을 표시하기 위해 다음과 같은 설명이 있습니다.

<%= Html.DropDownListFor(model => model.Category.Id, 
       new SelectList(ViewData["categories"] as IList<Category>, "Id", "Name"), 
       "-- Select Category --" ) %>

카테고리 컬렉션을 유지하기 위해 "비 유형"보기 데이터의 사용을 무시하십시오.

양식 게시물을 수신하는 조치 방법은 다음과 유사합니다. TransactionFilter 속성은 NHibernate Transaction Handling을 추가하고 예외가 발생하지 않고 유효성 검사가 성공하면 트랜잭션을 위반합니다.

[HttpPost]
[TransactionFilter]
public ActionResult Edit(int id, FormCollection collection) {
    var product = _repository.Load(id);

    // Update the product except the Id
    UpdateModel(product, null, null, new[] {"Id"}, collection);

    if (ModelState.IsValid) {
      return RedirectToAction("Details", new {id});
    }
    return View(product);
}

내 문제는 Product.category.id가 양식 (예 : 범주)에서 선택한 값으로 설정되어 있다는 것입니다. 기본 모델 바인더를 사용하면 다음 유형의 nhibernate 예외가 발생합니다.

identifier of an instance of Name.Space.Entities.Category was altered from 4 to 2

제품에는 이미 카테고리가 할당되어 있기 때문에 그다지 의미가 있으며 기존 카테고리의 주요 키 만 변경되고 있습니다. 다른 카테고리 인스턴스가 대신 할당되어야합니다.

이 문제를 처리하기 위해 사용자 정의 모델 바인더가 만들어 질 수 있지만이 작업을 수행하는 더 간단한 방법이 있습니까? 이를 처리하도록 도메인 엔티티를 수정할 수 있습니까?

도움이 되었습니까?

해결책 3

당시 우리가 선택한 솔루션은 다음과 비슷했습니다.

TryUpdateModel(product, null, null, new[] {"Category"}, collection);
int categoryId;
if (int.TryParse(collection["Category.Id"], NumberStyles.Integer, CultureInfo.InvariantCulture, out categoryId) && categoryId > 0) {
    product.Category = _categoryRepository.Load(categoryId);
}
else {
    product.Category = null;
}

우리는 단순히 모델 바인더에게 연관 속성을 배제하고 수동으로 처리하도록 지시합니다. 예쁘지는 않지만 당시에 일했습니다 ....

다른 팁

다음 줄을 변경하여 편집 페이지에서 콤보 상자와 비슷한 문제를 해결했습니다.

@Html.DropDownListFor(x => x.Employee.Id, new SelectList(ViewBag.Employees, "Id", "DisplayName"))

~에 의해

@Html.DropDownListFor(x => x.Employee, new SelectList(ViewBag.Employees, "Id", "DisplayName"))

브라이언이 제안한 것처럼 '.id'를 제거했습니다. 변경 전에 모델에는 직원의 ID 만 포함되었으며 변경 후 바인더는 직원의 모든 세부 사항을 모델에로드했습니다.

문제없이 LINQ에서 SQL 클래스와 유사한 기술을 사용했습니다. 나는 당신이 이것을 위해 사용자 정의 모델 바인더가 필요하다고 생각하지 않습니다. UpdateModel은 첨부 된 카테고리 하위 클래스가 아닌 제품 클래스를 업데이트해야합니다. DropdownListfor 헬퍼로 생성 된 HTML을 점검하십시오. 요소의 이름은 무엇입니까? 제품 테이블 (예 : "CategoryId"또는 "Product.categoryId"Not "Category.Id")의 외국 키 필드의 이름이어야합니다. "category.id"인 경우 - DropdownListfor의 첫 번째 매개 변수를 "model => model.category"또는 "model => model.categoryId"(또는 외국 키 필드가 무엇이든)로 변경하십시오. 이로 인해 UpdateModel은 카테고리 클래스 ID가 아닌 제품 클래스에서 외국 키 필드 만 업데이트해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top