vtfuture / RequireJSDotNet

RequireJS for ASP.NET MVC
http://requirejsnet.veritech.io
MIT License
94 stars 46 forks source link

default resolver bug #97

Open gregveres opened 7 years ago

gregveres commented 7 years ago

Hi

I am serving up a mobile specific view using View.mobile.cshtml. In some circumstances I need a different set of typescript files because the mobile version behaves differently because the view is different. So I figured I would be able to use a different layout file that invokes Html.RenderRequireJsSetup differently - specifically I would call it with a different EntryPointRoot and put all my mobile controllers under a directory called Controllers-Mobile.

This way I would have the following structure:

~/Scripts/ Controllers/Root/Player/Index.ts Controllers-Mobile/Controllers/Root/Player/Index.ts

But there is a bug on line 63 of the default resolver that is preventing me from doing this: https://github.com/vtfuture/RequireJSDotNet/blob/master/RequireJsNet/EntryPointResolver/DefaultEntryPointResolver.cs#L63

The bug is that, I believe, this line: var filePath = server.MapPath(entryPointRoot + entryPoint + ".js"); should be: var filePath = server.MapPath(resolvedEntryPointRoot + entryPoint + ".js");

earlier in the function you go through all the trouble to compute and update resolvedEntryPointRoot but then you don't use it. This is consistent with the behaviour I have seen, when I configure RenderRequireJsSetup as:

BaseUlr = Url.Content("~/Scripts/"); EntryPointRoot = "~/Scripts/";

things work fine because at the end of the day, EntryPointRoot is a full path to the file.

But when I configure it like this: BaseUlr = Url.Content("~/Scripts/"); EntryPointRoot = "Controllers-Mobile";

the file isn't found and no output is put into the html file.

I would work around this with my own instance of the IEntryPointResolver but I am not sure how to get my resolver class into the collection. I see lots of examples of implementations of IEntryPointResolvers on the web but nobody shows how they actually register their instance of the IEntryPointResolver so that it gets called. I have defined one my code but I think I have to figure out where in my code to add it to the collection. Can you give me a suggestion of where it should be added?

Thanks Greg

davidsk commented 7 years ago

The quickest solution would be to create and add a custom entrypointresolver. Once you've written your custom entrypointresolver, it can be added to the resolver collection in Application_Start

protected void Application_Start()
{
        // normal app_start stuff
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        // add custom resolver
        RequireJsNet.RequireJsOptions.ResolverCollection.Add(new MyCustomEntryPointResolver());
}
gregveres commented 7 years ago

Thanks @davidsk. That worked. But you can't Add to the ResolverCollection, you have to use Prepend. Otherwise by the time this code is executed, the default resolver is already in the collection first and it will always return non-null - at least in my case. So I wanted my resolver to be first.

But your answer got me going in the right direction. Thank you!

gregveres commented 7 years ago

Back to the bug and solution:

Aside from the bug, I think it would be nice if "Controllers" was not a hard coded part of the path. IMHO, I would change lines 48 and 49 to remove Controllers and then change the documentation to say that your EntryPointRoot should be "Controllers". This would give people the choice of where to place and what to call the Controllers directory.

This would be a breaking change though.