t4mvc / r4mvc Goto Github PK
View Code? Open in Web Editor NEWR4MVC is a Roslyn code generator for ASP.NET Core MVC apps that creates strongly typed helpers that eliminate the use of literal strings in many places
License: Apache License 2.0
R4MVC is a Roslyn code generator for ASP.NET Core MVC apps that creates strongly typed helpers that eliminate the use of literal strings in many places
License: Apache License 2.0
We need to find the root namespace of the project hosting R4MVC.
At the moment is it hard coded here.
We need to add support for MVC areas.
I'm not sure if that would be interesting/useful, but another option to add to the backlog would be to check the ability to generate some metadata for SignalR hub classes.
They'd be used in Javascript, of course, so not sure what would be the best case scenario, but we could at the very least generate js intellisense files!
We need to generate derived controller classes to use in the static MVC
class.
We need to generate the Links.Content
, Links.Scripts
etc constants.
How Can i Use R4MVC in MVC Core 1.1 ?
Dow You Have Nuget Package?
One of the things that should be tackled is preventing the root controllers and area names from clashing.
Say a user has a CatalogsController
, and also a Catalogs
area with further controllers. The MVC class would have a MVC.Catalogs
field for the controller and a MVC.Catalogs
property for the area.
I've added a basic check for this, and will rename the area property in the MVC class to MVC.CatalogsArea
. All other areas (that don't clash) don't get the suffix.
If someone has a CatalogsAreaController
or a CatalogsArea
area this will of course cause a clash, but I'm not handling that, since there's no practical reason to have a controller or area named this way :)
Does that sound reasonable?
(a patch to finish this logic will be in the next pull request late this week)
An obvious move eventually, but there are a couple things blocking us, currently.
Issue one will have to be handled first. Luckily, I managed to get it to work (sort of) on a clean environment, with a small workaround. Currently I have the sdk path (with the build number) hardcoded in the app. I could add a small method to "autoconfigure" and point to the latest available build, until the final release is out, or the MSBuild bug is fixed.
Issue 2 is also manageable, since you can technically install the runtime as part of the AppVeyor script. Again, this would only be required until the final public release is out.
Hi Kevin,
Thought we should move our discussion here since this is what we are discussing.
I've gotten a bit further on today with generating the controller partial classes with support for inheritance and basic generics. Your changes made for testing look good but I'm not sure how to pull them into my fork as our approaches are slightly different.
Take a look if you want and see if there is anything in there that is helpful, happy to help if I can, roslyn is certainly "an adventure" :)
When you add a tool package to a project, VS adds it's path to the current PATH env variable to be able to run it's exe/cli/powershell commands. That works fine until you update that package. At that point the second package's path is added to the PATH variable, but since it's added at the end, and the previous path is still there, the first one takes precedence.
The end result is - after you update the tool and try to run it, it will run the old version of the code - until you restart Visual Studio (at which point it will re-populate the new PATH additions with only currently added packages).
The solution to this is to have a wrapper app that loads our tool as a library dynamically. This approach is implemented by the EFCore team, for example.
In the meantime, we have a "known issues" entry, saying if you update the package, you should restart your VS.
For alpha 1 I'm planning to add a simple workaround in the form of a uninstall.ps1
script that will remove the old version from the env PATH
I have just started playing with ASP.Net 5 and MVC 6, after creating a new project I instinctively added T4MVC and quickly found my way here! ๐
I see from the latest comments here, that MS are going to support single file generators and that T4 may not be dead.
I'm wondering how close you guys are? Activity seems to have dropped off, is this related to the T4 news? It still seems like this project is a good idea going forward.
This is the main command of the package, which runs the primary purpose of the tool - evaluating the web project and generating R4Mvc classes. It can be either invoked in PowerShell (Generate-R4Mvc
) or in dotnet cli (dotnet r4mvc generate
). If executed within the same path as the web project, it can be triggered as is, otherwise you need to pass the project path as an argument.
Thanks to the dotnet configuration extensions, the main configuration will be picked up from the r4mvc.json
file in the root of the web project. Alternatively, you can also pass arguments in the command line to the tool (documentation will follow). I think it would be great if we also stored the configuration parameters in the json file if they haven't already been stored there to ensure that each consecutive run on the tool will generate consistent results.
Tasks:
We need to enable running unit tests on the build server.
I think we had some conflicts with the AppVeyor built in test test discovery and runner. At the moment we are not running tests using k test
or AppVeyor's built in test runner.
To finish the work started in PR #35.
The following settings will be expressed as arrays:
StaticFilesFolders
ExcludedStaticFileExtensions
ExcludedViewExtensions
When the configuration sub system supports arrays we can add these to the r4mvc.json
file.
@wwwlicious and I started this project with the support of @davidebbo back in the in the heady days of the K runtime, DNX, and the MVC 6 betas. Things were moving fast and we were unable to keep up with the changes.
We have some working code from the ~beta4 timeframe. Since then there have been many changes to the framework. Most notably for this project the ICompileModule
hook was dropped at some point.
Due to time constraints and other commitments @wwwlicious and I haven't had the time to dedicate to this project to move it forwards. Today we are officially asking for new maintainers to take it forward.
Please post a comment here if you're interested and I'll give you push access to the repro. Later I'll open admin access to the new maintainer(s).
Thanks to everyone who's shown interest in the project to date.
At the moment, this is either ignored (best case), or no code will be identified by the compiler in the first place (worst case!)
When R4Mvc.Tools loads a web project, we have to identify the target framework of that project, and possibly configure MSBuild to pick a desired framework. Need to test that with multi targeted projects, as well as identifying the differences based on which framework comes first in that list.
We need to override the action methods on our derived controller classes.
As vNext now has an interface common for all actionresults, IActionResult, it shouldn't be required to have specific overloads for subtypes like ViewResult, JsonResult etc so it should result in far fewer extensions required.
https://github.com/T4MVC/T4MVC/blob/master/T4MVCExtensions/T4Extensions.cs#L13
We need to figure out how to unit test R4MVC.
The entry point is currently a CSharpCompilation
, but it may be more useful to use the IBeforeCompileContext
instead. Questions:
CSharpCompilation
or IBeforeCompileContext
to invoke the generator?T4MVC uses a number of interfaces and classes which do not need to be generated in the target project such as IT4MVCActionResult.
Suggest following the same idea and create coreclr compatible versions of the following folder https://github.com/T4MVC/T4MVC/tree/master/T4MVCExtensions
I am trying to figure out if *4MVC should be abandoned.
In beta4 the ContentFiles
property has been removed from the Project
class. We need to remove our dependency on this property.
Creation of a DiagnosticAnalyzer to look for instances of
@Html.ActionLink("Link text", "actionname", "controllername", routevaluedictionary, null)
and suggest codefix to
@Html.ActionLink("Link text", MVC.ControllerName.ActionName(args))
We need to generate partial controller classes to hold the view and action name constants.
We are getting false positives on the build sever.
This build failed but it is showing green in AppVeyor.
This command will remove any generated code files from the project, created by R4Mvc. It might not be used a lot, but it might be useful in some circumstances.
Removing T4MVC is relatively easy (just delete the T4MVC.* files from the project. Compared to that, R4Mvc generates *.generated.cs
files for each controller, next to the controller files. The main reason for that is the auto-nesting feature in .NET Core projects - doing it this way removes clutter. The added benefit is when the user looks at the list of changes in his project in the commit window, the generated files will be next to the controller files.
The side effect is that removing R4Mvc becomes more complicated, since you have to trace and remove all the .generated.cs files from the project, making sure you only remove the R4Mvc ones.
The command can be invoked either in PowerShell (Remove-R4Mvc
) or in dotnet cli (dotnet r4mvc remove
). We'll also have a parameter to also remove the r4mvc.json
file.
We need figure out how to do DI in R4MVC.
I think we can hook into the framework's DI container using theIServiceProvider
. Questions:
We need to generate the action name constants in our generated partial controller classes.
We need to find where on disk the project.json
file is for the project hosting R4MVC, so we write out our generated .cs
files.
At the moment it is hard coded here.
I didn't see which tag helper causes this in ASP.NET, but they do, so we'll probably have to do the same.
This is pretty important for #50 alpha1, I think
Seems like the MSBuild/dotnet team has made some changes which has broken the build process once again. This is affecting a number of other projects, so it's not limited to us. One possible reason is that this was introduced in the dotnet core 2.0 preview 2.
I'll be investigating it deeper, and hopefully will find either a way to avoid the issue, or find a workaround for it. Until then, the build might fail on your machines.
While both the PowerShell and toe dotnet cli tooling will run the same executable, they will be invoked somewhat separately. The PowerShell commands are triggered by the PS Module bundled with the R4Mvc.Tools
package, and already works well.
For the dotnet cli to work, we need to either register the package as a cli tool package, or have a separate package to do that. So far I'm leaning towards the second approach, and will have to make it trigger the code from the first package.
There are some complications about this. Mainly because it seems like the DotNetCliTool packages have to have the same frameworks as the web project, otherwise they will be marked as incompatible. Since the tool itself runs .NET Framework code, and AspNetCore projects can run on .NET Core, this prevented me from registering the R4Mvc.Tools
project as a cli tool.
I'm still experimenting with some options, and will try find the best approach. I believe this should be a required feature for v1, since not everyone runs their projects on Windows in VS :)
For the alpha 1 release, I'll add some very basic documentation, mostly based on the docs from T4MVC.
Before the final v1 release, we have to make sure that
If a controller or action has the RequireHttpsAttribute, the links generated should ensure the url generated will be directing the user to a secure page.
We need to make existing controllers into partial
classes and make all the action methods virtual
.
Generate Typescript or Javascript class to allow client side generation of Action Urls and StaticContent links by expanding on the functionality of the Url.JavaScriptReplaceableUrl abilities of T4MVC to support fully-fledged client side MVC helpers functions.
more of a V2 wish at the moment though.
T4MVC has many features, and some technical debt to overcome.
What features should we carry over to R4MVC?
The core features we plan to implement are:
Do we need to support these features in v1, in vnext, another future release or can we drop support for them?
Follow on from #48.
master
and PRs) should automatically publish to MyGet.master
(i.e. create a release in GitHub) we should automatically publish to NuGet.org.The tag helpers are working as expected and the mvc-action
currently supports both synchronous and async actions. The issue is that these two types of actions have a different return type (IActionResult
vs Task<IActionResult>
)
In the tag helper code I've set the type of that attribute as object
to allow both types of methods to be accepted, and am type checking when generating the url, but that doesn't seem ideal.
I've added additional "fake" attributes with the same name, which gives me the benefit of showing the other accepted action result types in intellisense, which is my current workaround.
Options that I came up with so far are:
object
, but it accepts all actions in a consistent way, and the intellisense provides users with hints on data typesmvc-action
and mvc-action-async
IActionResult
in the tag helpers. For async actions, users will have to invoke .Result
<a mvc-action="MVC.Home.Index().Result">Async Index</a>
I'm interested to know what others thing would work best
So T4MVC uses an xml file, gen'd if it doesn't exist and otherwise left untouched between updates
I think a r4mvc.json file is probably the most natural vnext translation to hold some of the common settings like helper namespace and staticfile folders.
One other possibility to allow customisations/configuration is by providing either delegates or method overrides accessible in the R4MvcCompiler class where string settings cannot easily accomplish this. e.g.
// R4MVC project
public class R4MVCCompilerModule : ICompileModule
{
private Func<string> getFilePath;
....
private string GetGeneratedFilePath(Project project)
{
return this.getFilePath == null ? Path.Combine(project.ProjectDirectory, SyntaxHelpers.R4MvcFileName) : this.getFilePath.Invoke();
}
protected void SetGeneratedFilePath(Func<string> filePath)
{
this.getFilePath = filePath;
}
}
// target project
public class R4MvcCompiler : R4MVCCompilerModule
{
public R4MvcCompiler()
{
// user can pass in their own delegate
this.SetGeneratedFilePath(() => @"c:\mycustompath\gen.cs");
}
}
We need to generate the view name constants in our generated partial controllers.
T4MVC has hooks allowing users to customise the generated code. We should support something similar too.
Splitting off from #20.
We need to generate some boilerplate helper methods on our generated partial controllers.
These are the methods added by T4MVC:
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected RedirectToRouteResult RedirectToAction(ActionResult result)
{
var callInfo = result.GetT4MVCResult();
return RedirectToRoute(callInfo.RouteValueDictionary);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected RedirectToRouteResult RedirectToAction(Task<ActionResult> taskResult)
{
return RedirectToAction(taskResult.Result);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected RedirectToRouteResult RedirectToActionPermanent(ActionResult result)
{
var callInfo = result.GetT4MVCResult();
return RedirectToRoutePermanent(callInfo.RouteValueDictionary);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected RedirectToRouteResult RedirectToActionPermanent(Task<ActionResult> taskResult)
{
return RedirectToActionPermanent(taskResult.Result);
}
Do we need to keep the [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
attributes?
@artiomchi I've created a milestone and moved the issues I think we need for a first alpha into it. Do you think there is anything else to add? There is also the v1 backlog for other items to be picked up in later alphas and betas, and a backlog for anything else after v1.
@davidebbo I'm going to setup some automated deployments to MyGet / NuGet.org soon (see #49). Would you like to be listed as a package owner on NuGet (you are an owner here after all)?
/cc @wwwlicious
ASP.NET Core MVC added a new entity called View Components. They're similar to partial views / child actions, but more powerful and much better implemented.
I think R4MVC should also add support for them (although the initial core functionality takes priority ofc)
docs: https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components
Create a diagnosticanalyzer to look for usages of
public ActionResult Index()
{
View("index")
}
and codefix to replace with
public ActionResult Index()
{
View(Views.Index)
}
Currently only controllers marked R4MvcExclude are excluded from the rewriter and are not returned in the enumerable for generation.
Will need to exclude marking nonaction methods as virtual in the rewriter and exclude them from generation also.
This command will evaluate the web project and display the status of R4Mvc within said project - specifically checking if R4Mvc has already been invoked for the project, as well as displaying project configuration from the r4mvc.json
file, if present. It can either be invoked in PowerShell (Get-R4MvcStatus
) or in dotnet cli (dotnet r4mvc
)
Optionally, when triggered in PowerShell, we can output the results to a PS Object, which could help with some automation (if the user wants it)
If we are compiling for two or more frameworks, the generator is run for both of them. We only need to run once as the code we produce is the same each time. See PR #34.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.