잊지 않겠습니다.

DomainModel은 모두다 구성이 마쳐진 상태로 가정하고 MVC에 구성하는 방법에 대해서 알아본다.

먼저, web.config에 configSections에 castle속성과 IRepository에 대한 속성을 등록하고, httpModules에 Lifestyle에 대한 module을 등록한다.


	
		
Data Source=HOME-PC\SQLEXPRESS;Initial Catalog=SportsStore;Integrated Security=True;Pooling=False

다음, WindsorControllerFactory를 생성한다. WindsorControllerFactory는 DefaultControllerFactory를 상속하며, ControllerInstance를 저장하고 반환하는데 사용된다.

public class WindsorControllerFactory : DefaultControllerFactory
{
    private WindsorContainer container;

    public WindsorControllerFactory()
    {
        container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
        var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes() 
                              where typeof(IController).IsAssignableFrom(t) select t;
        foreach(Type t in controllerTypes)
        {
            container.AddComponentWithLifestyle(t.FullName, t, LifestyleType.Transient);
        }
    }

    protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
    {
        return (IController)container.Resolve(controllerType);
    }
}
마지막으로 Controller의 생성자를 이용해서 사용될 DomainModel의 interface를 등록하는 것으로 완료할 수 있다.
public class ProductController : Controller
{
    private IProductRepository _productRepository;
    public ProductController(IProductRepository productRepository)
    {
        _productRepository = productRepository;
    }


    public ViewResult List()
    {
        return View(_productRepository.Products.ToList());
    }
}

상당히 간단한데 왜 외워지지가 않는 것일까.; Castle에 대해서는 두번째 포스트인데 포스트 내용이 비스무리하다. -_-
Posted by Y2K
,
.NET Framework 4.0Beta2 로 작성된 application들은 NUnit에서 테스트가 불가능하다. NUnit는 .NET 2.x대의 base assembly만이 테스트가 가능하도록 작성되어 있기 때문이다.

그래서 MS의 xUnit test 를 이용해서 RouteData Test Code를 작성해보면 다음과 같다.
먼저, 가장 기본적인 RouteCollection을 생성하고, 테스트할 MVC application의 Route를 등록시킨다.
그리고 RouteCollection.GetRouteData(HttpBaseContext)를 이용해서 들어온 HttpBaseContext에 대한 RouteData를 확인한다.


[TestMethod]
public void TestMethod1()
{
    RouteCollection routeConfig = new RouteCollection();
    RouteApp.MvcApplication.RegisterRoutes(routeConfig);    
    RouteData routeData = routeConfig.GetRouteData(HttpBaseContext);
}


문제는 HttpBaseContext를 생성하는 것인데. Mock을 이용하면 간단하게 해결 할 수 있다.
다음 코드는 Mock을 이용해서 HttpBaseContext를 생성하는 코드이다.


private static Mock MakeMockHttpContext(string url)
{
    var mockHttpContext = new Mock();

    var mockRequest = new Mock();
    //HttpContext에 Request 설정
    mockHttpContext.Setup(x => x.Request).Returns(mockRequest.Object);
    //HttpRequest의 relative url로 사용자 지정 url 설정
    mockRequest.Setup(x => x.AppRelativeCurrentExecutionFilePath).Returns(url);

    var mockResponse = new Mock();
    //HttpContext에 Response 설정
    mockHttpContext.Setup(x => x.Response).Returns(mockResponse.Object);
    //HttpResponse에서 사용자 Url을 그냥 pass시키도록 ApplyAppPathModifier 수정
    mockResponse.Setup(x => x.ApplyAppPathModifier(It.IsAny())).Returns(x => x);            

    return mockHttpContext;
}


최종적으로 완성된 코드는 다음과 같다.

[TestMethod]
public void TestMethod1()
{
    RouteCollection routeConfig = new RouteCollection();
    RouteApp.MvcApplication.RegisterRoutes(routeConfig);

    var mockHttpContext = MakeMockHttpContext("~/");
    RouteData routeData = routeConfig.GetRouteData(mockHttpContext.Object);

    Assert.IsNotNull(routeData.Route);            
    Console.WriteLine(routeData.Values.ToString());
}
Posted by Y2K
,
1. URL을 깔끔하고 사용자 친화적으로 만들자.
URL은 폰트나 이미지 못지 않게 중요한 UI의 일부라는 것을 인식하자.
  • URL이 응용 프로그램의 일부가 아닌 그가 담고 있는 내용을 서술하도록 변경하자.
  • ID나 숫자보다는 본문 제목을 표시하도록 하자.
  • 가능하다면 HTML 페이지에 대하여 파일명 확장자를 사용하지 말라. (.aspx와 같은) 하지만 특수한 형식들 jpg, pdf, zip에 대해서는 사용하는 것이 좋다. 사용자가 예상하는 파일명 확장자에 대해서는 그것을 사용하는 것이 훨씬 좋다.
  • 계측적인 느낌을 만들자(/Product/Menswear/Shirts/Red와 같이)
  • 대소문자를 구별하지 말자
  • 기술적인 기호나 코드, 연속문자를 피하라. 만일 단어의 분리를 원한다면 -를 사용해서 연걸해라
  • URL을 변경하지 말아라. 깨져버린 링크는 사업의 손실과 같다. URL을 변경하는 경우 301 영구적 재전송을 통해 가능한 길게 기존 URL 스키마를 유지해야지 된다.
  • URL은 짧아야 하고, 입력하기 쉬워야지 하며, 편집하기 용의하고 지속적이여야지 된다. 그리고 사이트 구조를 투영하고 있어야지 된다
참고 자료 : http://www.w3.org/Provider/Style/Url

2. HTTP 관습을 따르자
  • GET과 POST를 정확히 선택하라. 기본적인 지침에 따르면 GET 요청은 모든 readonly 정보 검색에 사용되어야지 되며 POST 요청은 서버상에서 상태를 변경하는 write 작업에 사용되어야 한다는 것이다. 표준에 입각한 관점에서 보면 GET요청은 안전한 상호요청을 위한 것이며 POST 요청은 안전하지 않은 상호요청에 의한 것이다.
  • GET 요청은 접근이 가능해야지 된다. 모든 정보는 URL에 포함되어 있으며 그렇기 때문에 주소를 링크하거나 즐겨찾기가 가능해야지 된다.
  • 상태를 변경하는 작업에 GET을 사용하면 안된다.
  • 질의 문자열의 사용에 유의하라. 질의 문자열은 사용자 친화성을 고려하지 않는 곳이나 링크하지 않을 곳을 찾아서 사용하는 것이 좋다. 또한 알고리즘에 값을 넣어서 결과를 얻어오는 때에도 사용할 수 있다.

3. HTTP 재전송의 정확한 유형을 사용하자.
HTTP 재전송의 경우 301과 302로 정의되어 있는데, 둘다 모두 브라우저로 하여금 GET 요청을 통해 새로운 URL로 이동하게 된다. 그러나 301과 302는 검색엔진에서 차이가 있으며 이는 다음과 같다.

301 : 영구적인 이동. 이는 이 URL이 영원히 사용되지 않으며, 다시는 요쳥되지 않아야지 함을 의미한다. 그리고 모든 Inbound 링크는 새로운 URL로 변경되어야지 되는 것을 의미한다. 검색엔진에서는 새로운 URL하에서 Context처리를 한다. URL Schema가 변경되었을 때 사용되어야지 된다.
302 : 임시적인 이동. 클라이언트는 이번 요청만을 위해서 제공하는 대체 URL을 사용한다. 검색엔진은 기존의 URL을 유지한다.

4. 검색엔진 최적화
검색 엔진의 종류에 따라 각기 다른 엔진 순위를 가지고 있으나, 많은 Blogger들이 실험으로 증명한 사항들은 다음과 같다.
  • URL에 적절한 키워드를 사용하라.
  • 질의 문자열 매개변수를 최소화하고 단어구분자로 밑줄을 사용하지 말라
  • 컨탠츠의 각 부분에 대해 단일 URL, 즉 정규 URL을 주도록 하라. HTTP 301 재전송을 통해서 현재의 정규 URL을 유지하라.
  • 모든 Contents는 접근 가능해야지 된다. Contents가 javascript, flash, silverlight의 탐색에 의하여 종속적이지 않아야지 된다. (불행하게도 우리나라에서 가장 안지켜지는 부분인것 같다. 모든 사이트가 Flash toolbar로 떡칠이 되어있으니.;;)




Posted by Y2K
,