How to create actionlink inside threads

I have a stream that sends emails. I need to create ActionLinks as part of the email content so that the user can click on the link and redirect to the website, exactly to the desired page. I tried to instantiate the class UrlHelperand use it Actionto generate the link, but since the threads are not executed in the context of any request, I get exceptions during the generation of ActionLink.

How can i do this?

+3
source share
2 answers

You need to fake the HttpContextBase and pass this UrlHelper, which you can use in a stream without an HttpContext. Here is a rough idea, although you need to create a class around it, etc., This is a quick proof of concept, since unit tests also do not have an HttpContext.

[TestFixture]
public class RouteTestClass
{
    private UrlHelper helper;

    public RouteTestClass()
    {
        MvcApplication.RegisterRoutes(RouteTable.Routes); //You dont need to do this if its done in global.asax!
        var c = new RequestContext(new FakeContext(), new RouteData());
        helper = new UrlHelper(c, RouteTable.Routes);
    }

    [Test]
    public void TestGetHomeIndex()
    {
        var url = helper.Action("Index", "Home");
        Assert.AreEqual("/",url);
    }
}

public class FakeContext : HttpContextBase
{
    public override HttpRequestBase Request { get { return new FakeRequest(); } }
    public override HttpResponseBase Response { get { return new FakeResponse(); } }
}

public class FakeRequest : HttpRequestBase
{
    public override string ApplicationPath { get { return "/"; } }
    public override NameValueCollection ServerVariables { get { return new NameValueCollection(); } }
}

public class FakeResponse : HttpResponseBase
{
    public override string ApplyAppPathModifier(string virtualPath)
    {
        return virtualPath;
    }
}

Edit

Having looked at this , I cleaned up the code a bit, since I do not need to create fakes for HttpRequestBase and HttpResponseBase.

[TestFixture]
public class RouteTestClass
{
    private UrlHelper helper;

    public RouteTestClass()
    {
        MvcApplication.RegisterRoutes(RouteTable.Routes);
        var req = new HttpRequest("/", "http://www.yoururl.com", "");
        var resp = new HttpResponse(new StringWriter());
        var httpContext = new HttpContext(req, resp);
        var c = new RequestContext(new HttpContextWrapper(httpContext), new RouteData());
        helper = new UrlHelper(c, RouteTable.Routes);
    }

    [Test]
    public void TestGetHomeIndex()
    {
        var url = helper.Action("Index", "Home");
        Assert.AreEqual("/",url);
    }
}
+1
source

You can grant a stream access to an existing UrlHelperone by passing it to the stream starter. If your thread is started from the controller, just pass UrlHelperin the controller property Url:

new Thread(
    urlHelper =>
    {
        var url = 
            ((UrlHelper)urlHelper)
            .Action("Index", "Home", new { Id = 5 });
        // use url here
    }
).Start(Url);
0
source

Source: https://habr.com/ru/post/1764542/


All Articles