Использование почты и Hangfire в подсайтах
Я пытался использовать Почтовый на моем сайте MVC5. Когда я размещаю свою веб-страницу на дочернем сайте, т.е. http://localhost/Subsite я получаю сообщение об ошибке
- Виртуальный путь '/' сопоставляется с другим приложением, что запрещено
Я отлаживал его до того момента, когда создается ControllerContext, HttpContext не устанавливается правильно. Так как я запускаю Почтовый от Hangfire, HttpContext.Current всегда нулевой. Почтовая служба создает ContollerContext, используя код ниже.
ControllerContext CreateControllerContext()
{
// A dummy HttpContextBase that is enough to allow the view to be rendered.
var httpContext = new HttpContextWrapper(
new HttpContext(
new HttpRequest("", UrlRoot(), ""),
new HttpResponse(TextWriter.Null)
)
);
var routeData = new RouteData();
routeData.Values["controller"] = EmailViewDirectoryName;
var requestContext = new RequestContext(httpContext, routeData);
var stubController = new StubController();
var controllerContext = new ControllerContext(requestContext, stubController);
stubController.ControllerContext = controllerContext;
return controllerContext;
}
string UrlRoot()
{
var httpContext = HttpContext.Current;
if (httpContext == null)
{
return "http://localhost";
}
return httpContext.Request.Url.GetLeftPart(UriPartial.Authority) +
httpContext.Request.ApplicationPath;
}
Как я могу указать UrlRoot, чтобы вместо тяги по умолчанию для localhost его можно было использовать на основе моего дочернего сайта?
2 ответа
Ниже приведено еще одно возможное решение, которое я считаю более элегантным, чем выше. Это также решает проблему, возникающую при доступе к приложению MVC во время выполнения фонового процесса.
public static void SendTypedEmailBackground()
{
try
{
var engines = new ViewEngineCollection();
var viewsPath = Path.GetFullPath(HostingEnvironment.MapPath(@"~/Views/Emails"));
var eng = new FileSystemRazorViewEngine(viewsPath);
engines.Add(eng);
var email = new WebApplication1.Controllers.EmailController.TypedEmail();
email.Date = DateTime.UtcNow.ToString();
IEmailService service = new Postal.EmailService(engines);
service.Send(email);
}
catch(Exception ex)
{
throw ex;
}
}
Я следовал инструкциям здесь http://docs.hangfire.io/en/latest/tutorials/send-email.html чтобы отправить свое электронное письмо. Метод в учебнике ниже
public static void NotifyNewComment(int commentId)
{
// Prepare Postal classes to work outside of ASP.NET request
var viewsPath = Path.GetFullPath(HostingEnvironment.MapPath(@"~/Views/Emails"));
var engines = new ViewEngineCollection();
engines.Add(new FileSystemRazorViewEngine(viewsPath));
var emailService = new EmailService(engines);
// Get comment and send a notification.
using (var db = new MailerDbContext())
{
var comment = db.Comments.Find(commentId);
var email = new NewCommentEmail
{
To = "yourmail@example.com",
UserName = comment.UserName,
Comment = comment.Text
};
emailService.Send(email);
}
}
Я обнаружил, что проблема заключалась в том, что FileSystemRazorViewEngine не использовался почтовой службой. Чтобы заставить это работать, я должен был убедиться, что FileSystemRazorViewEngine был первым доступным механизмом. Я тогда удалил это, потому что я не хотел, чтобы это было двигателем по умолчанию. Ниже мой обновленный метод.
public static void NotifyNewComment(int commentId)
{
// Prepare Postal classes to work outside of ASP.NET request
var viewsPath = Path.GetFullPath(HostingEnvironment.MapPath(@"~/Views/Emails"));
var eng = new FileSystemRazorViewEngine(viewsPath));
ViewEngines.Engines.Insert(0, eng);
var emailService = new EmailService(engines);
// Get comment and send a notification.
using (var db = new MailerDbContext())
{
var comment = db.Comments.Find(commentId);
var email = new NewCommentEmail
{
To = "yourmail@example.com",
UserName = comment.UserName,
Comment = comment.Text
};
emailService.Send(email);
ViewEngines.Engines.RemoveAt(0)
}
}