The idea is to reuse build application on multiple child application as a lot of Views and Codes need to be same on all children application. This approach can be a good candidate for a multitenant application, some sort of pluggable architecture or reusing MVC app as parent project.
There are three things need to be done to achieve.
This has to be configured on child application to copy from application build event. It can be done by going into project property => Build Events => Edit Post Built (Post-built event command line).
Ex:
xcopy "$(SolutionDir)"..\“App.Common\App.Common.Web\Views” “$(ProjectDir)\CommonAppLoc\Views\” /s /i /y /f
xcopy "$(SolutionDir)"..\“App.common\App.Common\App.Common.Web\Areas” “$(ProjectDir)\CommonAppLoc\Areas\” /s /i /y /f
xcopy "$(SolutionDir)"..\“\App.Common\App.Common.Web\Content” “$(ProjectDir)\CommonAppLoc\Content\” /s /i /y /f
There are several macros which can help out to get the desired path. In this one, $(SolutionDir) is used to get solution path and then put the relative path for the application. It can be customized based on a need basis.
In above example, I am trying to copy View, Areas and Content to child application to get physical files.
Area registration on child application.
To consume some other controller, Area registration needs to be done in a different manner with namespace parameter to refer codes of the parent controller from somewhere else.
NOTE: If want to have the same path as parent application then Area registration on parent application can be and consumed on child application to have paths
Custom View path through customized Razor view engine.
Since the other app Views are copied to the local project, we need to set up our View Engine to look into the newly copied paths. To do that the default view engine needs to override to have those paths.
If we look into the source code of MVC then can have a better idea https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/RazorViewEngine.cs.
So, we can inherit the same RazorViewEngine and customize the paths based on desired locations.
The above code is just registering CommonApp path for the application to get the views. The CustomViewLoc path is used to add precedence for views. If any view need further customization then it can be just placed under CustomViewLoc, if it is not present then it picks from original view.
Finally, the View engine registration
This above view engine needs to be registered under Global.asax
There are three things need to be done to achieve.
- Project built event to copy Views from the parent application.
- Area registration on child application.
- Custom View path through customized Razor view engine.
This has to be configured on child application to copy from application build event. It can be done by going into project property => Build Events => Edit Post Built (Post-built event command line).
Ex:
xcopy "$(SolutionDir)"..\“App.Common\App.Common.Web\Views” “$(ProjectDir)\CommonAppLoc\Views\” /s /i /y /f
xcopy "$(SolutionDir)"..\“App.common\App.Common\App.Common.Web\Areas” “$(ProjectDir)\CommonAppLoc\Areas\” /s /i /y /f
xcopy "$(SolutionDir)"..\“\App.Common\App.Common.Web\Content” “$(ProjectDir)\CommonAppLoc\Content\” /s /i /y /f
There are several macros which can help out to get the desired path. In this one, $(SolutionDir) is used to get solution path and then put the relative path for the application. It can be customized based on a need basis.
In above example, I am trying to copy View, Areas and Content to child application to get physical files.
Area registration on child application.
To consume some other controller, Area registration needs to be done in a different manner with namespace parameter to refer codes of the parent controller from somewhere else.
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "User_default",
url: "User/{controller}/{action}/{id}",
defaults: new { action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "App.Common.Web.Areas.User,Controllers" }
);
}
NOTE: If want to have the same path as parent application then Area registration on parent application can be and consumed on child application to have paths
Custom View path through customized Razor view engine.
Since the other app Views are copied to the local project, we need to set up our View Engine to look into the newly copied paths. To do that the default view engine needs to override to have those paths.
If we look into the source code of MVC then can have a better idea https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/RazorViewEngine.cs.
So, we can inherit the same RazorViewEngine and customize the paths based on desired locations.
public class AppCommonRazor
: RazorViewEngine
{
/// <summary>
/// Initializes a new instance of the <see cref="AppCommonRazor"/> class.
/// </summary>
public AppCommonRazor()
{
ViewLocationFormats = ViewLocationFormats.Concat(new string[]
{
"~/CommonApp/Views/CustomViewLoc/{1}/{0}.cshtml",
"~/CommonApp/Views/CustomViewLoc/{0}.cshtml",
"~/CommonApp/Views/{1}/{0}.cshtml",
"~/CommonApp/Views/{0}.cshtml",
}).ToArray();
PartialViewLocationFormats = PartialViewLocationFormats.Concat(new string[]
{
"~/CommonApp/Views/CustomViewLoc/{1}/{0}.cshtml",
"~/CommonApp/Views/CustomViewLoc/Shared/{0}.cshtml",
"~/CommonApp/Views/{1}/{0}.cshtml",
"~/CommonApp/Views/Shared/{0}.cshtml",
}).ToArray();
AreaViewLocationFormats = AreaViewLocationFormats.Concat(new string[]
{
"~/CommonApp/Areas/{2}/Views/CustomViewLoc/{1}/{0}.cshtml",
"~/CommonApp/Areas/{2}/Views/CustomViewLoc/Shared/{0}.cshtml",
"~/CommonApp/Areas/{2}/Views/{1}/{0}.cshtml",
"~/CommonApp/Areas/{2}/Views/Shared/{0}.cshtml",
}).ToArray();
AreaPartialViewLocationFormats = AreaPartialViewLocationFormats.Concat(new string[]
{
"~/CommonApp/Areas/{2}/Views/CustomViewLoc/{1}/{0}.cshtml",
"~/CommonApp/Areas/{2}/Views/CustomViewLoc/Shared/{0}.cshtml",
"~/CommonApp/Areas/{2}/Views/{1}/{0}.cshtml",
"~/CommonApp/Areas/{2}/Views/Shared/{0}.cshtml",
}).ToArray();
}
}
The above code is just registering CommonApp path for the application to get the views. The CustomViewLoc path is used to add precedence for views. If any view need further customization then it can be just placed under CustomViewLoc, if it is not present then it picks from original view.
Finally, the View engine registration
This above view engine needs to be registered under Global.asax
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new MasterAppCommonRazor());
Comments
Post a Comment