2016-12-10 6 views
0

asp.net MVC 웹 응용 프로그램이 있습니다. 그것은 사용자가 일부를 집어 들고 세부 사항을 보는 등의 엔티티 목록입니다.모델 바인더의 필링 엔티티 대 바인더를 대체하는 외부 메서드 대

이 응용 프로그램의 대부분의 동작에는 매개 변수로 Entity이 있습니다. 예를 들어 :

[Authorize] 
public ActionResult Details(Entity entity) 
{ 
    ... 
    return View(); 
} 

나는 세션에서이 엔티티를 유지하고 URL에서 ID로 모델 바인더에서이 매개 변수를 입력합니다.

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
{ 
    var httpContext = controllerContext.HttpContext; 
    var values = httpContext.Request.RequestContext.RouteData.Values; 

    if (!values.ContainsKey("id")) return null; 

    var id = values["id"].ToString(); 
    var obj = httpContext.Session["Entities"]; 
    var list = (List<Entity>) obj; 
    return list?.SingleOrDefault(x => x.Id == id); 
} 

그러나 시간은 사용자가 세션 객체가 비어있을 때 행동에 접속을 시도 할 수 경우입니다 시간을 잴 : 그것은 것 같습니다. 예를 들어 사용자는 전자 메일을 통해 URL을 가져오고 세션에 Entity를 삽입하는 코드는 생략합니다.

이 경우 가장 적합한 수정 프로그램은 무엇입니까?

1.

는 바인더에 엔티티를 받고 구현 : 나는 바인더에 추가 충전 로직을 구현해야의 때문에

var id = values["id"].ToString(); 
    var obj = httpContext.Session["Entities"]; 
    var list = (List<Entity>) obj; 
    var entity = list?.SingleOrDefault(x => x.Id == id); 

    if(null==entity){ 
     entity = repository.GetEntity(id); 
     //set entity in session 
    } 

    return entity; 

이 방법은 불쾌한 보인다. 또한 바인더에 저장소를 삽입 할 수 없습니다. 그러나이 방법은 간단하고 구현하기 쉽습니다.

2. 바인더를 제거하고 일부 get 메소드 추가 : 모든

제거 바인더를하고 다음 방법으로 엔티티 모든 작업을 변경 :

[Authorize] 
public ActionResult Details() 
{ 
    Entity entity = GetEntity(); 
    ... 
    return View(); 
} 
private Entity GetEntity() 
{ 
    var id = ... //get id from http request. 
    var list = (List<Entity>)Session["Entities"]; 
    var entity = list?.SingleOrDefault(x => x.Id == id); 

    if(null==entity){ 
     entity = repository.GetEntity(id); 
     //set entity in session 
    } 

    return entity; 
} 

내가 지금 저장소의 주입을 구현할 수 있습니다 코드는 안전하지만 추한 것처럼 보입니다.

어떤 솔루션이 가장 좋습니까? 다른 구현을 놓친 것이 가능합니까?

+0

는 왜 옵션 2 추한 모습 생각 : 당신의 바인더를 등록 할 때 다음

public class MyModelBinder : DefaultModelBinder { private readonly Func<IRepository> repositoryProvider; public MyModelBinder(Func<IRepository> repositoryProvider) { this.repositoryProvider = repositoryProvider; } public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var id = ... //get id from http request. var list = (List<Entity>)Session["Entities"]; var entity = list?.SingleOrDefault(x => x.Id == id); if (null == entity) { IRepository repository = this.repositoryProvider(); entity = repository.GetEntity(id); //set entity in session } return entity; } } 

과 :하지만 당신은 공장을 사용할 수 있을까? 그것의 정상적인 접근 방식, 그리고 ModelBinder는 저장소를 호출해서는 안된다 (그리고 당신은 메소드가'id'를위한 매개 변수를 가져야한다). –

+0

@StephenMuecke 'id'에 대한 좋은 지적. 그것은 일반적인 접근이지만 우아하게 보이지 않습니다. – RredCat

답변

1

바인더에 로직 을 추가로 구현해야하므로이 방법이 고약 해 보입니다. 또한 바인더에 저장소를 삽입 할 수 없습니다.

모델 바인더에서 종속성 삽입을 제대로 수행 할 수 없습니다.

ModelBinders.Binders[typeof(Entity)] = new MyModelBinder(
    () => DependencyResolver.Current.GetService<IRepository>() 
);