2013-08-09 7 views
1

내 사이트의 특정 페이지에 대한 링크가 포함 된 전자 메일을 보내는 정적 클래스가 있습니다. 그 링크는 동적으로 코드를 생성지고 :서비스에서 호출 된 MVC UrlHelper

UrlHelper urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext); 
string url = urlHelper.Action("Details", "Product", new { id = ticketId }, "http"); 

문제는 내가 지금 주기적으로 현재 날짜와 만든 날짜를 비교하여 자동으로 그 메일을 전송하는 서비스가 있습니다. 물론 코드가 충돌하고 HttpContext.Current은 null입니다 (요청이 아니기 때문에).

나는 그런 몇 가지 시도 :

private static System.Web.Routing.RequestContext requestContext; 
private static System.Web.Routing.RequestContext RequestContext { 
    get 
    { 
     if(requestContext == null) 
      requestContext = HttpContext.Current.Request.RequestContext; 
     return requestContext; 
    } 
} 

을하지만이 UrlHelper.Action에 대한 두 번째 RequestContext을 필요로 할 때 null 참조 예외를 말하는 충돌합니다.

내 서비스에서 메일 메서드를 호출 할 때 UrlHelper 또는 HttpContext를 저장/기억/전달하지 못했습니다.

+0

것은, 당신이 ControllerContext를 사용한다. 이 코드는 어디에서 살고 있습니까? 라이브러리에 있으면 URL 도우미를 만드는 메서드에 적절한 컨텍스트를 전달해야합니다. 그러나 URL과 같은 웹 특정 항목을 볼 수 없습니다. 웹 레이어이므로 프로젝트의 웹 레이어에 있어야합니다. –

+0

나는 UrlHelper와 함께 보내는 모든 것들을하는 MailMethods라는 정적 클래스를 가지고있다. 실제 문제는 이제 동일한 솔루션 파일에있는 모든 서비스에 액세스 할 수 있지만 HttpContext가없는 별도의 서비스가 있다는 것입니다. 현재 ... – CodingYourLife

+4

@yourmother 다음에는 디자인 문제가 있습니다. 도우미 *가 HttpContext.Current에 의존하는 경우 사용할 수있는 환경에서만 사용해야합니다. 그렇지 않으면 HttpContext.Current에 대한 필요성을 리팩토링해야합니다. – James

답변

1

귀하의 모든 도움에 감사드립니다. 필자의 경우 URL을 미리 정의 할 수는 없었다. 내 문제에 대한 해결책을 찾았습니다. 나는 그것이 가장 아름다운 코드가 아닐지도 모른다. 그러나 그것은 꽤 잘 작동한다. 그리고 아무도 더 좋은 것을 가지고있는 것처럼 보이지 않는다. 그래서 어떤 downvotes도 기쁘게하지 마라. global.asax.cs에서

나는이 클래스 추가 :

class FirstRequestInitialisation 
{ 
    private static string host = null; 

    private static Object s_lock = new Object(); 

    // Initialise only on the first request 
    public static void Initialise(HttpContext context) 
    { 
     if (string.IsNullOrEmpty(host)) 
     { //host isn't set so this is first request 
      lock (s_lock) 
      { //no race condition 
       if (string.IsNullOrEmpty(host)) 
       { 
        Uri uri = HttpContext.Current.Request.Url; 
        host = uri.Scheme + Uri.SchemeDelimiter + uri.Host + ":" + uri.Port; 

        //open EscalationThread class constructor that starts anonymous thread that keeps running. 
        //Constructor saves host into a property to remember and use it. 
        EscalationThread et = new EscalationThread(host); 
       } 
      } 
     } 
    } 
} 

을 그리고 나는이 추가 : 각을 모든이 FirstRequestInitialisation 클래스를 요청 : 무슨 일

void Application_BeginRequest(Object source, EventArgs e) 
{ 
    FirstRequestInitialisation.Initialise(((HttpApplication)source).Context); 
} 

Explaination을 컨텍스트를 매개 변수로 사용하여 Initialise 메서드를 사용하여 호출됩니다. 컨텍스트가 Application_BeginRequest (Application_Start와 유사하지 않음)에 알려져 있기 때문에 이것은 결코 문제가되지 않습니다. Initialize Method는 Thread가 한번 호출되었을 때 여전히 충돌을 일으키지 않도록 잠금을 유지하도록 처리합니다. 나는 정말로 의사 소통을 할 수 없기 때문에 내 서비스를 제거하고 그 대신에 실을 만들기로 결심했다. 이 초기화 메서드에서는 매개 변수로 호스트를 사용하여 클래스 생성자 인 EscalationThread를 호출합니다. 이 생성자에서 나는 계속 실행중인 스레드를 만들고 시작합니다.

나는 아직도있는 HttpContext이없는 및 UrlHelper를 사용할 수 없습니다하지만 호스트를 가지고 같은 물건을 할 수 있습니다 : 당신이 컨트롤러에 있다면 string urlInMail = this.host + string.Format("/{0}/{1}/{2}", "Product", "Details", product.Id);