1

こんにちは私はコードを発見した特定の時刻に電子メールを送信しようとしています。 global.asax.csオン は、メール機能では、私はGmailでメールを送信することだし、体の上に、私は、文字列Thread.Timer with HttpContextが機能しません

string body = ViewRenderer.RenderPartialView("~/Views/Shared/Email.cshtml", LEM); 
にレンダリング私のかみそりビューに文字列クラスに部分図を描画しています

protected void Application_Start() 
{ 
    ETHOS.Controllers.HomeController mail = new Controllers.HomeController(); 
    mail.ScheduleService(); 
    private void SchedularCallback(object e) 
    { 
     this.WriteToFile("Simple Service Log: {0}"); 
     getData();//Email function 
     this.ScheduleService(); 
    } 
    public void ScheduleService() 
    { 
     try 
     { 
      Schedular = new Timer(new TimerCallback(SchedularCallback)); 
      string mode = "DAILY"; 
      this.WriteToFile("Simple Service Mode: " + mode + " {0}"); 
      //Set the Default Time. 
      //DateTime d = DateTime.Today; 
      //TimeSpan t = new TimeSpan(12, 40, 00); 
      //DateTime scheduledTime = d.Date + t; 
      DateTime scheduledTime = DateTime.Now.AddSeconds(30); 
      if (DateTime.Now > scheduledTime) 
      { 
       //If Scheduled Time is passed set Schedule for the next day. 
       // scheduledTime = scheduledTime.AddDays(1); 
       scheduledTime = scheduledTime.AddDays(1); 
      } 
      TimeSpan timeSpan = scheduledTime.Subtract(DateTime.Now); 
      string schedule = string.Format("{0} day(s) {1} hour(s) {2} minute(s) {3} seconds(s)", timeSpan.Days, timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds); 
      this.WriteToFile("Simple Service scheduled to run after: " + schedule + " {0}"); 
      //Get the difference in Minutes between the Scheduled and Current Time. 
      int dueTime = Convert.ToInt32(timeSpan.TotalMilliseconds); 

      //Change the Timer's Due Time. 
      Schedular.Change(dueTime, Timeout.Infinite); 
     } 
     catch (Exception ex) 
     { 
      WriteToFile("Simple Service Error on: {0} " + ex.Message + ex.StackTrace); 
     } 
    } 

を提出します

問題は、HttpContext.Current.ItがHttpContext.Current = nullを表示しないことです。私はどちらも同じhttpcontextで両方を使用することができますので、なぜそれはHttpContextを取得していないthatsのスレッドを作成していると思う。 はここHttpContextは、HTTPリクエストの有効期間内でのみ使用可能です

public class ViewRenderer:ETHOS.Controllers.HomeController 
     {/// <summary> 
    /// Required Controller Context 
    /// </summary> 
    protected ControllerContext Context { get; set; } 

    /// <summary> 
    /// Initializes the ViewRenderer with a Context. 
    /// </summary> 
    /// <param name="controllerContext"> 
    /// If you are running within the context of an ASP.NET MVC request pass in 
    /// the controller's context. 
    /// Only leave out the context if no context is otherwise available. 
    /// </param> 
    public ViewRenderer(ControllerContext controllerContext = null) 
    { 
     System.Web.HttpContext ctx = (System.Web.HttpContext) Session["ctx"]; 
     // Create a known controller from HttpContext if no context is passed 
     if (controllerContext == null) 
     { 
      if (System.Web.HttpContext.Current != null) 
       controllerContext = CreateController<EmptyController>().ControllerContext; 
      else 
       throw new InvalidOperationException(
        "ViewRenderer must run in the context of an ASP.NET " + 
        "Application and requires HttpContext.Current to be present."); 
     } 
     Context = controllerContext; 
    } 

    /// <summary> 
    /// Renders a full MVC view to a string. Will render with the full MVC 
    /// View engine including running _ViewStart and merging into _Layout   
    /// </summary> 
    /// <param name="viewPath"> 
    /// The path to the view to render. Either in same controller, shared by 
    /// name or as fully qualified ~/ path including extension 
    /// </param> 
    /// <param name="model">The model to render the view with</param> 
    /// <returns>String of the rendered view or null on error</returns> 
    public string RenderViewToString(string viewPath, object model = null) 
    { 
     return RenderViewToStringInternal(viewPath, model, false); 
    } 

    /// <summary> 
    /// Renders a full MVC view to a writer. Will render with the full MVC 
    /// View engine including running _ViewStart and merging into _Layout   
    /// </summary> 
    /// <param name="viewPath"> 
    /// The path to the view to render. Either in same controller, shared by 
    /// name or as fully qualified ~/ path including extension 
    /// </param> 
    /// <param name="model">The model to render the view with</param> 
    /// <returns>String of the rendered view or null on error</returns> 
    public void RenderView(string viewPath, object model, TextWriter writer) 
    { 
     RenderViewToWriterInternal(viewPath, writer, model, false); 
    } 


    /// <summary> 
    /// Renders a partial MVC view to string. Use this method to render 
    /// a partial view that doesn't merge with _Layout and doesn't fire 
    /// _ViewStart. 
    /// </summary> 
    /// <param name="viewPath"> 
    /// The path to the view to render. Either in same controller, shared by 
    /// name or as fully qualified ~/ path including extension 
    /// </param> 
    /// <param name="model">The model to pass to the viewRenderer</param> 
    /// <returns>String of the rendered view or null on error</returns> 
    public string RenderPartialViewToString(string viewPath, object model = null) 
    { 
     return RenderViewToStringInternal(viewPath, model, true); 
    } 

    /// <summary> 
    /// Renders a partial MVC view to given Writer. Use this method to render 
    /// a partial view that doesn't merge with _Layout and doesn't fire 
    /// _ViewStart. 
    /// </summary> 
    /// <param name="viewPath"> 
    /// The path to the view to render. Either in same controller, shared by 
    /// name or as fully qualified ~/ path including extension 
    /// </param> 
    /// <param name="model">The model to pass to the viewRenderer</param> 
    /// <param name="writer">Writer to render the view to</param> 
    public void RenderPartialView(string viewPath, object model, TextWriter writer) 
    { 
     RenderViewToWriterInternal(viewPath, writer, model, true); 
    } 

    /// <summary> 
    /// Renders a partial MVC view to string. Use this method to render 
    /// a partial view that doesn't merge with _Layout and doesn't fire 
    /// _ViewStart. 
    /// </summary> 
    /// <param name="viewPath"> 
    /// The path to the view to render. Either in same controller, shared by 
    /// name or as fully qualified ~/ path including extension 
    /// </param> 
    /// <param name="model">The model to pass to the viewRenderer</param> 
    /// <param name="controllerContext">Active Controller context</param> 
    /// <returns>String of the rendered view or null on error</returns> 
    public static string RenderView(string viewPath, object model = null, 
            ControllerContext controllerContext = null) 
    { 
     ViewRenderer renderer = new ViewRenderer(controllerContext); 
     return renderer.RenderViewToString(viewPath, model); 
    } 

    /// <summary> 
    /// Renders a partial MVC view to the given writer. Use this method to render 
    /// a partial view that doesn't merge with _Layout and doesn't fire 
    /// _ViewStart. 
    /// </summary> 
    /// <param name="viewPath"> 
    /// The path to the view to render. Either in same controller, shared by 
    /// name or as fully qualified ~/ path including extension 
    /// </param> 
    /// <param name="model">The model to pass to the viewRenderer</param> 
    /// <param name="writer">Writer to render the view to</param> 
    /// <param name="controllerContext">Active Controller context</param> 
    /// <returns>String of the rendered view or null on error</returns> 
    public static void RenderView(string viewPath, TextWriter writer, object model, 
            ControllerContext controllerContext) 
    { 
     ViewRenderer renderer = new ViewRenderer(controllerContext); 
     renderer.RenderView(viewPath, model, writer); 
    } 

    /// <summary> 
    /// Renders a partial MVC view to string. Use this method to render 
    /// a partial view that doesn't merge with _Layout and doesn't fire 
    /// _ViewStart. 
    /// </summary> 
    /// <param name="viewPath"> 
    /// The path to the view to render. Either in same controller, shared by 
    /// name or as fully qualified ~/ path including extension 
    /// </param> 
    /// <param name="model">The model to pass to the viewRenderer</param> 
    /// <param name="controllerContext">Active Controller context</param> 
    /// <param name="errorMessage">optional out parameter that captures an error message instead of throwing</param> 
    /// <returns>String of the rendered view or null on error</returns> 
    public static string RenderView(string viewPath, object model, 
            ControllerContext controllerContext, 
            out string errorMessage) 
    { 
     errorMessage = null; 
     try 
     { 
      ViewRenderer renderer = new ViewRenderer(controllerContext); 
      return renderer.RenderViewToString(viewPath, model); 
     } 
     catch (Exception ex) 
     { 
      errorMessage = ex.GetBaseException().Message; 
     } 
     return null; 
    } 

    /// <summary> 
    /// Renders a partial MVC view to the given writer. Use this method to render 
    /// a partial view that doesn't merge with _Layout and doesn't fire 
    /// _ViewStart. 
    /// </summary> 
    /// <param name="viewPath"> 
    /// The path to the view to render. Either in same controller, shared by 
    /// name or as fully qualified ~/ path including extension 
    /// </param> 
    /// <param name="model">The model to pass to the viewRenderer</param> 
    /// <param name="controllerContext">Active Controller context</param> 
    /// <param name="writer">Writer to render the view to</param> 
    /// <param name="errorMessage">optional out parameter that captures an error message instead of throwing</param> 
    /// <returns>String of the rendered view or null on error</returns> 
    public static void RenderView(string viewPath, object model, TextWriter writer, 
            ControllerContext controllerContext, 
            out string errorMessage) 
    { 
     errorMessage = null; 
     try 
     { 
      ViewRenderer renderer = new ViewRenderer(controllerContext); 
      renderer.RenderView(viewPath, model, writer); 
     } 
     catch (Exception ex) 
     { 
      errorMessage = ex.GetBaseException().Message; 
     } 
    } 


    /// <summary> 
    /// Renders a partial MVC view to string. Use this method to render 
    /// a partial view that doesn't merge with _Layout and doesn't fire 
    /// _ViewStart. 
    /// </summary> 
    /// <param name="viewPath"> 
    /// The path to the view to render. Either in same controller, shared by 
    /// name or as fully qualified ~/ path including extension 
    /// </param> 
    /// <param name="model">The model to pass to the viewRenderer</param> 
    /// <param name="controllerContext">Active controller context</param> 
    /// <returns>String of the rendered view or null on error</returns> 
    public static string RenderPartialView(string viewPath, object model = null, 
              ControllerContext controllerContext = null) 
    { 
     ViewRenderer renderer = new ViewRenderer(controllerContext); 
     return renderer.RenderPartialViewToString(viewPath, model); 
    } 

    /// <summary> 
    /// Renders a partial MVC view to string. Use this method to render 
    /// a partial view that doesn't merge with _Layout and doesn't fire 
    /// _ViewStart. 
    /// </summary> 
    /// <param name="viewPath"> 
    /// The path to the view to render. Either in same controller, shared by 
    /// name or as fully qualified ~/ path including extension 
    /// </param> 
    /// <param name="model">The model to pass to the viewRenderer</param> 
    /// <param name="controllerContext">Active controller context</param> 
    /// <param name="writer">Text writer to render view to</param> 
    /// <param name="errorMessage">optional output parameter to receive an error message on failure</param> 
    public static void RenderPartialView(string viewPath, TextWriter writer, object model = null, 
              ControllerContext controllerContext = null) 
    { 
     ViewRenderer renderer = new ViewRenderer(controllerContext); 
     renderer.RenderPartialView(viewPath, model, writer); 
    } 


    /// <summary> 
    /// Internal method that handles rendering of either partial or 
    /// or full views. 
    /// </summary> 
    /// <param name="viewPath"> 
    /// The path to the view to render. Either in same controller, shared by 
    /// name or as fully qualified ~/ path including extension 
    /// </param> 
    /// <param name="model">Model to render the view with</param> 
    /// <param name="partial">Determines whether to render a full or partial view</param> 
    /// <param name="writer">Text writer to render view to</param> 
    protected void RenderViewToWriterInternal(string viewPath, TextWriter writer, object model = null, bool partial = false) 
    { 
     // first find the ViewEngine for this view 
     ViewEngineResult viewEngineResult = null; 
     if (partial) 
      viewEngineResult = ViewEngines.Engines.FindPartialView(Context, viewPath); 
     else 
      viewEngineResult = ViewEngines.Engines.FindView(Context, viewPath, null); 

     if (viewEngineResult == null) 
      throw new FileNotFoundException(); 

     // get the view and attach the model to view data 
     var view = viewEngineResult.View; 
     Context.Controller.ViewData.Model = model; 

     var ctx = new ViewContext(Context, view, 
            Context.Controller.ViewData, 
            Context.Controller.TempData, 
            writer); 
     view.Render(ctx, writer); 
    } 

    /// <summary> 
    /// Internal method that handles rendering of either partial or 
    /// or full views. 
    /// </summary> 
    /// <param name="viewPath"> 
    /// The path to the view to render. Either in same controller, shared by 
    /// name or as fully qualified ~/ path including extension 
    /// </param> 
    /// <param name="model">Model to render the view with</param> 
    /// <param name="partial">Determines whether to render a full or partial view</param> 
    /// <returns>String of the rendered view</returns> 
    private string RenderViewToStringInternal(string viewPath, object model, 
               bool partial = false) 
    { 
     // first find the ViewEngine for this view 
     ViewEngineResult viewEngineResult = null; 
     if (partial) 
      viewEngineResult = ViewEngines.Engines.FindPartialView(Context, viewPath); 
     else 
      viewEngineResult = ViewEngines.Engines.FindView(Context, viewPath, null); 

     if (viewEngineResult == null || viewEngineResult.View == null) 
      throw new FileNotFoundException();//Resources.ViewCouldNotBeFound); 

     // get the view and attach the model to view data 
     var view = viewEngineResult.View; 
     Context.Controller.ViewData.Model = model; 

     string result = null; 

     using (var sw = new StringWriter()) 
     { 
      var ctx = new ViewContext(Context, view, 
             Context.Controller.ViewData, 
             Context.Controller.TempData, 
             sw); 
      view.Render(ctx, sw); 
      result = sw.ToString(); 
     } 

     return result; 
    } 


    /// <summary> 
    /// Creates an instance of an MVC controller from scratch 
    /// when no existing ControllerContext is present  
    /// </summary> 
    /// <typeparam name="T">Type of the controller to create</typeparam> 
    /// <returns>Controller for T</returns> 
    /// <exception cref="InvalidOperationException">thrown if HttpContext not available</exception> 
    public static T CreateController<T>(RouteData routeData = null, params object[] parameters) 
       where T : Controller, new() 
    { 
     // create a disconnected controller instance 
     T controller = (T)Activator.CreateInstance(typeof(T), parameters); 

     // get context wrapper from HttpContext if available 
     HttpContextBase wrapper = null; 
     if (System.Web.HttpContext.Current != null) 
      wrapper = new HttpContextWrapper(System.Web.HttpContext.Current); 
     else 
      throw new InvalidOperationException(
       "Can't create Controller Context if no active HttpContext instance is available."); 

     if (routeData == null) 
      routeData = new RouteData(); 

     // add the controller routing if not existing 
     if (!routeData.Values.ContainsKey("controller") && !routeData.Values.ContainsKey("Controller")) 
      routeData.Values.Add("controller", controller.GetType().Name 
                 .ToLower() 
                 .Replace("controller", "")); 

     controller.ControllerContext = new ControllerContext(wrapper, routeData, controller); 
     return controller; 
    } 

} 

/// <summary> 
/// Empty MVC Controller instance used to 
/// instantiate and provide a new ControllerContext 
/// for the ViewRenderer 
/// </summary> 
public class EmptyController : Controller 
{ 
} 

答えて

2

以下RendererViewクラスです。このようなバックグラウンドスレッドでは、外部で使用することはできません。また、implement recurring background tasks in an ASP.NET applicationsにとっては悪い習慣とみなされます。推奨される方法は、このタスクをWebアプリケーションからオフロードし、Windowsスケジューラによって定期的に実行されるWindowsサービスまたはコンソールアプリケーションに配置することです。

あなたが推奨するアプローチに反してこれを行うことを依頼する場合は、using the Razor engine outside of an ASP.NET applicationと考えて、HttpContextに依存しないようにしてください。

+0

この場合WindowsサービスまたはWebサービスを使用する必要があります –

+2

電子メールを送信するWindowsサービス。 –

1

これは、HTTPリクエストスレッド以外のスレッドからHttpContext.Currentにアクセスできないためです。コンテキストを渡すのではなく、そのことについて何もできることはありません。危険である可能性があります。

私は、ASP.NET(Windowsサービスなど)とは別のプロセスでコードを実行することをお勧めします。

+0

Windowsサービスを使用している場合、どのように私は剃刀のビューで電子メールテンプレートを作成できますか? –

+0

特別なパッケージRazorEngineがあり、ASP.NETなしでRazorビューエンジンを呼び出すことができます。あなたはそれを見つけることができます[ここ](https://razorengine.codeplex.com/)。 –

関連する問題