Search code examples
asp.net-mvcasp.net-mvc-5hangfirepostal

Using Postal and Hangfire in Subsite


I have been trying to use Postal on my MVC5 site. When I host my webpage a subsite ie, http://localhost/Subsite I am receiving the error

  • The virtual path '/' maps to another application, which is not allowed

I have debugged it down to when the ControllerContext is being created the HttpContext isn't getting set correctly. Since I'm running Postal from Hangfire the HttpContext.Current is always null. Postal creates the ContollerContext using the code below.

        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;
    }

How can I specify the UrlRoot so that instead of pulling the default of localhost to pull it based on my subsite?


Solution

  • Below is another possible solution that I think is more elegant than above. It also resolves an issue that appears when accessing the MVC application while the background process is being executed.

    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;
        }
    }