【问题标题】:Sending email using resulted razor view in MailKit在 MailKit 中使用结果剃刀视图发送电子邮件
【发布时间】:2016-11-28 18:58:40
【问题描述】:

希望我能用简单的方式解释我的要求:

在.Net Core中,我们可以在使用View(FileName, Model)发送模型数据后显示.cshtml视图。

有没有办法将Model 发送到.cshtml 文件,这样我就不会显示结果视图,而是使用Mailkit 通过电子邮件发送附件

【问题讨论】:

    标签: razor .net-core mailkit


    【解决方案1】:

    感谢Paris Polyzos 和他的article

    我找到了解决方案,很喜欢分享它,希望有人从中受益,或改进它。

    首先:我们需要创建service来将Rasor转换为String,代码Razor2String.cs如下:

    using System
    using System.IO;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.Abstractions;
    using Microsoft.AspNetCore.Mvc.ModelBinding;
    using Microsoft.AspNetCore.Mvc.Razor;
    using Microsoft.AspNetCore.Mvc.Rendering;
    using Microsoft.AspNetCore.Mvc.ViewFeatures;
    using Microsoft.AspNetCore.Routing;
     
    namespace Project.Utilities
    {
        public interface IViewRenderService
        {
            Task<string> RenderToStringAsync(string viewName, object model);
        }
     
        public class ViewRenderService : IViewRenderService
        {
            private readonly IRazorViewEngine _razorViewEngine;
            private readonly ITempDataProvider _tempDataProvider;
            private readonly IServiceProvider _serviceProvider;
             public ViewRenderService(IRazorViewEngine razorViewEngine,
                ITempDataProvider tempDataProvider,
                IServiceProvider serviceProvider)
            {
                _razorViewEngine = razorViewEngine;
                _tempDataProvider = tempDataProvider;
                _serviceProvider = serviceProvider;
            }
     
            public async Task<string> RenderToStringAsync(string viewName, object model)
            {
                var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider };
                var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
     
                using (var sw = new StringWriter())
                {
                    var viewResult = _razorViewEngine.FindView(actionContext, viewName, false);
                    if (viewResult.View == null)
                    {
                        throw new ArgumentNullException($"{viewName} does not match any available view");
                    }
     
                    var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
                    {
                        Model = model
                    };
     
                    var viewContext = new ViewContext(
                        actionContext,
                        viewResult.View,
                        viewDictionary,
                        new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),
                        sw,
                        new HtmlHelperOptions()
                    );
     
                    await viewResult.View.RenderAsync(viewContext);
                    return sw.ToString();
                }
            }
        }
    }
    

    第二:我们需要将"preserveCompilationContext": true添加到buildOptions,所以project.json变成:

    {
      "version": "1.0.0-*",
      "buildOptions": {
        "debugType": "portable",
        "emitEntryPoint": true,
        "preserveCompilationContext": true
      },
      "dependencies": {
        "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
        "Microsoft.AspNetCore.Mvc": "1.0.1",
        "MailKit":"1.10.0"
      },
      "frameworks": {
        "netcoreapp1.0": {
          "dependencies": {
            "Microsoft.NETCore.App": {
              "type": "platform",
              "version": "1.0.1"
            }
          },
          "imports": "dnxcore50"
        }
      }
    }
    

    第三:我们需要将service添加到Startup类中的ConfigureServices,这样Startup.cs文件就变成了:

    using System;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.DependencyInjection;
    using Project.Utilities;
    
    public class Startup
        {
            public void ConfigureServices(IServiceCollection services)
            {
                // Add framework services.
                services.AddMvc();
                 // Add application services.
                services.AddScoped<IViewRenderService, ViewRenderService>();
            }
    
            public void Configure(IApplicationBuilder app)
            {
                app.UseMvc();
    
                app.Run(async (context) =>
                {
                    await context.Response.WriteAsync(
                        "Hello World of the last resort. The Time is: " +
                        DateTime.Now.ToString("hh:mm:ss tt"));
                });
            }
        }
    

    第四:定义你的Model,类似于users.cs

    namespace myApp
    {
         public class users {
            public string   UserId {get; set;}
            public string   UserName {get; set;}
        } 
    }
    

    第五:创建View模板,在Views文件夹中,类似Views/Razor2String.cshtml

    Hello
    <hr/>
    
    @{
        ViewData["Title"] = "Contact";
    }
    <h2>@ViewData["Title"].</h2>
    <h3>user id: @Model.UserId</h3>
    

    第六:Program.cs 简单如下:

    using System.IO;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    
    namespace myApp
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                var host = new WebHostBuilder()
                    .UseContentRoot(Directory.GetCurrentDirectory())
                    .UseKestrel()
                    .UseUrls("http://localhost:50000")
                    .UseStartup<Startup>()
                    .Build();
                host.Run();
            }
        }
    }
    

    第七:主要部分,'Email.cs':

    using System;
    using System.IO;
    using Microsoft.AspNetCore.Mvc;
    
    using Project.Utilities;
    using System.Threading.Tasks;
    
    using MailKit.Net.Smtp;   // for SmtpClient
    using MimeKit;  // for MimeMessage, MailboxAddress and MailboxAddress
    
    namespace myApp
    {
        [Route("api")]
        public class RenderController : Controller
        {
            private readonly IViewRenderService _viewRenderService;
            public RenderController(IViewRenderService viewRenderService)
            {
                _viewRenderService = viewRenderService;
            }
         
          [Route("sendEmail")]
          public async Task sendEmail()
            {
                var viewModel = new users
                {
                    UserId = "cdb86aea-e3d6-4fdd-9b7f-55e12b710f78",
                    UserName = "iggy",
                };
         
                // Get the generated Razor view as String
                var result = await _viewRenderService.RenderToStringAsync("Razor2String", viewModel);
    
                MemoryStream stream = new MemoryStream ();
                StreamWriter writer = new StreamWriter(stream);
                writer.Write((String)result);
                writer.Flush();
                stream.Position = 0;
    
                var message = new MimeMessage();
                message.From.Add(new MailboxAddress("Hasan Yousef", "mySelf@gmail.com"));
                message.To.Add(new MailboxAddress("Personal", "myPersonalEmail@gmail.com"));
                message.Subject = "Email Test";
                var bodyBuilder = new BodyBuilder();
    
                bodyBuilder.HtmlBody = @"<div>HTML email body</Div>";
    
                bodyBuilder.Attachments.Add ("msg.html", stream);
    
                message.Body = bodyBuilder.ToMessageBody();
    
                using (var client = new SmtpClient())
                    {
                        client.Connect("smtp.gmail.com", 587);
                        client.AuthenticationMechanisms.Remove("XOAUTH2");  // due to enabling less secure apps access
                    Console.WriteLine("Prepairing the Email");
                        try{
                            client.Authenticate("mySelf@gmail.com", "myPSWD");
                            Console.WriteLine("Auth Completed");
                        }
                        catch (Exception e){
                        Console.WriteLine("ERROR Auth"); 
                        }
                        try{
                            client.Send(message);
                            Console.WriteLine("Email had been sent");
                        }
                        catch (Exception e){
                            Console.WriteLine("ERROR");
                        }
                        client.Disconnect(true);
                    }
            }
        }
    }
    

    如果您需要将字符串发送回浏览器,您可以使用:

      [Route("returnView")]
      public async Task<IActionResult> returnView()
        {
            var viewModel = new users
            {
                UserId = "cdb86aea-e3d6-4fdd-9b7f-55e12b710f78",
                UserName = "iggy",
            };
     
            // Get the generated Razor view as String
            var result = await _viewRenderService.RenderToStringAsync("Razor2String", viewModel);
            return Content(result);
        }
    

    如果您需要将结果发送到 AJAX 请求,您可以使用类似:

    public async Task<String> RenderInviteView()
    {
    .
    .
    .
    return result;
    }
    

    如果你想有单独的方法将字符串转换成流,比如GenerateStreamFromString(result),那么你可以使用using (Stream stream = GenerateStreamFromString(result)){ }调用它

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-14
      • 2023-03-18
      • 2017-02-17
      • 1970-01-01
      • 2015-09-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多