smsohan/MvcMailer

Mvc Mailer in area

Opened this issue · 7 comments

In my project i wan't to use MvcMailer, it's really nice.
For the structure of my project i wan't to put the mailer controllers + views in a separate area. But after i have done this the
e-mail body stay's empty, so the PopulateBody method can't find the view, i think he is looking in the root view folder instead of the area view folder.
Is is possible to use Mvc Mailer in a separate area?

This is an issue I have also experienced. I have had to temporarily move the mailing code out of the area but I would like a long term solution to this.

Then i think the right solution for me is to put the mailer in a separate project instead of an area.

I have also had this problem. For structural reasons, having to store the email views in the root of my application is annoying; it would be great to have area support for it.

ocdi commented

I had the reverse issue of this, using the mailer from within a controller area caused the views to be searched in the same area, yet the mailer was outside. Its because MailerBase creates its ControllerContext on demand with this code:

if (this.ControllerContext == null)
    this.CreateControllerContext();

This in turn uses

this.ControllerContext = new ControllerContext(this.CurrentHttpContext, RouteTable.Routes.GetRouteData(this.CurrentHttpContext), (ControllerBase) this);

For me I create my own ControllerContext in the constructor of my class, adding an new RouteData() to ensure no area is polluting it - for your case you could add the area you are after, like:

var data = new RouteData();
data.Values.Add("Area", "Mailers");
ControllerContext = new ControllerContext(base.CurrentHttpContext, data, this)

Hope this helps.

ocdi's answer is pretty close, I got it working like so:
//Ensure MvcMailer uses views from the Mails area
var data = new RouteData { Route = RouteTable.Routes["Mails_default"] };
ControllerContext = new ControllerContext(CurrentHttpContext, data, this);

So what this says is that a route called "Mails_default" exists where the mails reside

Just hit this issue as well 👍

I also ran into this issue because I'm creating a UserMailer from within a Web Api 2 Area, which doesn't include the area name in its route data.

I used @ocdi 's method and changed data.Values.Add("Area", "Mailers") to data.DataTokens["area"] = "MyAreaName" and it worked.

Using Web Api 2 and MVC 5.

So for anyone skimming, this is what my UserMailer constructor looks like:

public UserMailer()
        {
            MasterName = "_Layout";
            var data = new RouteData();
            data.DataTokens["area"] = "MCCI";
            this.ControllerContext = new System.Web.Mvc.ControllerContext(this.CurrentHttpContext, data, this);
        }