1

ASP.NET MVC3
を使用しています。.cshtmlビューがあり、それを文字列化してメール本文に組み込みたいと考えています。
これが私が使用する方法です:

//Renders a view to a string
private string RenderRazorViewToString(string viewName, object model)
{
    ViewData.Model = model;

    using (var sw = new System.IO.StringWriter())
    {
        var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
        var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
        viewResult.View.Render(viewContext, sw);
        viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
        
        return sw.GetStringBuilder().ToString();
    }
}

ActionResultAjax 呼び出しから呼び出されるメソッドからこのメソッドを呼び出すと、これは完全に機能します。

しかし、私は異常な状況に直面しています:

私のGlobal.asaxファイルには、10 分ごとに呼び出されるメソッドがあり、その目的は、過去 10 分間にデータベースに特別なレコードが作成されたかどうかを確認し、作成された場合はメールを送信することです。もちろん、メール本文はこの文字列化されたビューです。

ここに私のコードの一部があります:このメソッドは、この投稿に非常に触発されています

/* File : Gloabal.asax.cs */

private static CacheItemRemovedCallback OnMatchingCacheRemove = null;

protected void Application_Start()
{
    // ...
    AddMatchingTask("SendEmail", 600);
}

private void AddMatchingTask(string name, int seconds)
{
    OnMatchingCacheRemove = new CacheItemRemovedCallback(CacheItemMatchingRemoved);
    HttpRuntime.Cache.Insert(name, seconds, null, DateTime.UtcNow.AddSeconds(seconds), Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, OnMatchingCacheRemove);
}


//This method is called every 600 seconds
public void CacheItemMatchingRemoved(string k, object v, CacheItemRemovedReason r)
{
    using (MyEntities context = new MyEntities())
    {
        var qMatching = from m in context.MY_TABLE
                        where m.IsNew == true
                        select m;

        if (qMatching.Any())
        {
            MatchingController matchingController = new MatchingController();
            matchingController.SendEmail();
        }
    }

    // re-add our task so it recurs
    AddMatchingTask(k, Convert.ToInt32(v));
 }

このSendEmail()メソッドは、電子メールの本文を作成し、ビューを取得して、それを HTML 文字列に入れて送信する必要があります。

public void SendEmail()
{
     /* [...] Construct a model myModel */
     
     /* Then create the body of the mail */
     string htmlContent = RenderRazorViewToString("~/Views/Mailing/MatchingMail.cshtml", myModel);  
}
    

ここで、RenderRazorViewToString()(メソッドの本体はこの投稿の上部に記載されています) 次の行で失敗します:

var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);

ControllerContext を null にすることはできません

なぜ、この場合のみControllerContextがなのnullですか? 私はこの投稿を読みましたが、それを正しく理解していれば、これはコントローラーの書き込みを手動でインスタンス化したためです。

MatchingController matchingController = new MatchingController();

しかし、それ以外の方法で続行する方法がわかりません...

どんな助けでも歓迎です。
ありがとうございました

4

3 に答える 3

1

Web ヒットをシミュレートする代わりに、実際に Web ヒットをトリガーして、適切なコンテキストでビューをレンダリングできます。結果を受け取り、メールの本文に保存します。保険の見積もりについても同様のことをしなければなりませんでした。これが私のコードであり、その後にニーズに合わせて適応します。

    public ActionResult StartInsuranceQuote()
    {

        using (var client = new WebClient())
        {
            var values = new NameValueCollection
            {
                { "sid", DataSession.Id.ExtractSid() }
            };
            client.UploadValuesAsync(new Uri(Url.AbsoluteAction("QuoteCallback", "Quote")), values);
        }
        return PartialView();                
    }

これの鍵は、モデルから値のコレクションを設定することです。あなたはそれを提供しなかったので、説明のためにいくつかのプロパティを想定します:

    public void SendEmail(YourViewModel model)
    {
        using (var client = new WebClient())
        {
            var values = new NameValueCollection
            {
                { "Name",  model.Name },
                { "Product", model.Product },
                { "Color", model.Color },
                { "Comment", model.Comment }
            };
            string body = client.UploadValues(new Uri(Url.AbsoluteAction("GenerateBody", "RenderEmail")), values);

            // send email here
        }
    }

RenderEmailController:

    public ActionResult GenerateBody()
    {
        return View();
    }

GenerateBody.cshtml:

@foreach (string key in Request.Form.AllKeys)
{
    Response.Write(key + "=" + Request[key] + "<br />");
}

更新: AbsoluteAction は拡張メソッドであり、以下に含まれています

public static string AbsoluteAction(this UrlHelper url, string actionName, string controllerName, object routeValues = null)
{
    if (url.RequestContext.HttpContext.Request.Url != null)
    {
        string scheme = url.RequestContext.HttpContext.Request.Url.Scheme;
        return url.Action(actionName, controllerName, routeValues, scheme);
    }
    throw new Exception("Absolute Action: Url is null");
}
于 2015-02-05T16:06:06.423 に答える