I'm starting a new ASP.NET MVC project, and I decided to put my controllers in a different assembly. Evertyhing works fine, but I have hit a problem: I created a new area in my MVC Project, called Administration. I have an AdminController Class in my seperate assembly which is supposed to return views from my Admin area, but everytime it tries to return a view,
it looks for it in the wrong place (~/Admin/SomeView.cshtml Instead of ~/Administration/Admin/SomeView.cshtml)
How can I tell the controller to look for views in the wanted area?
Please take a look into this article. And also you problem was answered here.
Basically you will need to extend MvcViewEngine, to tell MVC to look for your Views in the different from standatd pathes:
public class YourMegaViewEngine : WebFormViewEngine
{
public YourMegaViewEngine ()
{
ViewLocationFormats = new string[]
{
"~/Views/Administration/{1}/{0}.cshtml" //I may be wrong for you case, but this is the place to puth you path
};
}
}
Related
I know what View Engine is, I preferred to use Razor view engine just because of its simple syntax over ASPX engine. Inbuilt view engine performs almost all task for you, then in what scenario I should create my own view engine,
I googled it but getting answers for How to create it and not when and why to create it.
Can any one help me to describe the real time scenario?
For example, you can change the view files locations that Razor searches with the help of custom view engine.
Normally, in MVC these locations are searched for partial views:
// Part of the RazorViewEngine implementation from the Asp.net MVC source code
PartialViewLocationFormats = new[]
{
"~/Views/{1}/{0}.cshtml",
"~/Views/{1}/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml"
};
Then add for example LayoutsPartialViews folder to Shared folder and add partial views which for example will be used only for layouts. And add for example ColorfuleHeader.cshtml to that location. And try to render that view via this:
#Html.Partial("ColorfulHeader");
Such exception will be throwned:
The partial view 'ColorfulHeader' was not found or no view engine
supports the searched locations. The following locations were
searched...:
So we must add this location to the searched locations. And for doing this we must create our custom view engine:
public class CustomLocationViewEngine : RazorViewEngine
{
public CustomLocationViewEngine()
{
PartialViewLocationFormats = new[] {
"~/Views/{1}/{0}.cshtml",
"~/Views/{1}/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml",
"~/Views/Shared/LayoutsPartialViews/{0}.cshtml",
"~/Views/Shared/LayoutsPartialViews/{0}.vbhtml",
};
}
}
Also, remember that the action invoker goes to each view engine in turn to see if a view can be found. By
the time that we are able to add our view to the collection, it will already contain the standard Razor View
Engine. To avoid competing with that implementation, we call the Clear method to remove any other
view engines that may have been registered, and then call the Add method to register our custom
implementation.
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomLocationViewEngine());
I have an ASP.NET vNext (5) project. I am trying to add two areas to the project. My question is, how do I register areas in vNext? The System.Web.Mvc namespace is gone, which is where AreaRegistrationContext was located. I started looking in the MVC source code on GitHub. I found the Area attribute. However, I'm not sure how to utilize it now.
Can someone please explain to me (or provide a link) of how to use Areas in ASP.NET vNext?
Thank you!
In vNext you register and configure the services you are going to use in Startup.cs. Area routes are added like normal routes. There is a sample here: https://github.com/aspnet/Mvc/blob/a420af67b72e470b9481d6b2eca29f7c7c2254d2/samples/MvcSample.Web/Startup.cs
You could add an MVC route for an area like this:
app.UseMvc(routes =>
{
routes.MapRoute("areaRoute", "{area:exists}/{controller}/{action}");
});
Or you could use a route attribute like this: [Route("[area]/Home")]
The [Area] attribute decorates controllers included in the area. It takes only one parameter, the name of the area. Here's an example: https://github.com/aspnet/Mvc/blob/a420af67b72e470b9481d6b2eca29f7c7c2254d2/samples/MvcSample.Web/Areas/Travel/Controllers/HomeController.cs
[Area("Travel")]
public class HomeController : Controller
{ //... }
I've seen several MVC4 tutorials that show how to access the index URL for a view, but I can't seem to reach a new view that I add.
I can access my home index at:
http://localhost:3214/
But if I create a new view (let's call it "NewView.cshtml") I can't access it from
http://localhost:3214/NewView.cshtml
Where would it be?
The page inspector expects the page to be at:
http://localhost:4244/Home/NewView
But it isn't there.
UPDATE:
In the solution explorer the file is located at:
MyProject/Views/Home/NewView.cshtml
OK - So think of your Views as merely html files (although they are not) - i.e. they are purely for display purposes. But they are not static like normal HTMLs - they have code.
Hence its the controller and the route that you need to understand.
The route is what you type in the browser. For instance /Home/NewView will be translated to HomeController, NewView action if thats how you have configured it. The default view is {controller}/{action}/{id} so try http://localhost:4244/Home/NewView/1
Now to properly display and code NewView you need to go to your HomeController and add a NewView action. Like:
public ActionResult NewView()
{
return View(); // This will automatically display the NewView.chtml view from the Home (or Shared) folder in your Views folder
}
Then go to your Routes (typically in your global.asax file and add it like:
routes.MapRoute(
"SomeUniqueRouteName",
"Home/NewView",
new { controller = "Home" action = "NewView" }
);
Then you can call it like http://localhost:4244/Home/NewView without the id cause you haev specified a route for it.
Let me know if you need any more help.
Currently in my web application I have plenty of lines like this:
Response.Redirect("~/Default.aspx");
etc. Now, I'm in the process of reorganizing aspx pages structure, as it's pretty flat - everything is in one folder. So I have to thoroughly search all the code in order to fix aspx paths. So my question is: is there any way to manage/organize web site pages structure in ASP .NET - some kind of SiteMap, so that I have a code similar to:
Response.Redirect(Pages.Default);
so that my code will be closed for modifications where some aspx pages are moved between folders?
I've written an open source project that will help you, http://navigation.codeplex.com/.
You list your pages and transitions in a config file. Here's an example:
<state key="Page1" page="~/Page1.aspx">
<transition key="Next" to="Page2"/>
</state>
<state key="Page2" page="~/Page2.aspx"/>
Then in your code you can move from Page1.aspx to Page2.aspx like this:
StateController.Navigate("Next");
Let me know if you're interested or need any help.
I don't think there there's any automatic solution, you'll probably end up building something yourself. You may want to check out the Asp.Net Sitemap stuff, although it's mainly focused on Navigation controls.
http://msdn.microsoft.com/en-us/library/yy2ykkab.aspx
I ran into the same issue you're facing on a few projects. One simple solution is to create constant/static/enums to represent the page names/urls:
public static class SiteMap {
public static readonly string Default = "/default.aspx";
}
which of course lets you do
Response.Redirect(SiteMap.Default);
But that was outgrown quickly as the pages required parameters passed in, and sooner or later you run into exactly the same problem with the parameter names. So we expanded on that idea by adding an Url factory class like
public static class SiteMap {
public static readonly string Article = "/blog/article.aspx";
}
public static class PageParams {
public static readonly string ArticleId = "aid";
}
public static class UrlFactory {
public static string GetUrlBlogArticle(int articleId){
return string.Format("/{0}?{1}={2}",SiteMap.Article, PageParams.ArticleId, articleId.ToString());
}
}
That approach ensures all the links work the same way and include the same parameters. By setting up a PageParams constants class the landing pages/controls code are a little cleaner too, since you can do
public void method(){
var articleId = Request[PageParams.ArticleId];
}
rather than have random request parameter names everywhere.
Hope that gives you some ideas.
I'm very new to ASP.NET MVC and this is probably a really obvious thing...Basically, I can't access the "Forum" view which I had created inside "Home" folder (because I need a link to Forum on my main homepage.). I was wondering if it's okay to just move the Forum view into the Shared folder?
Is this somehow very bad practice? It seems like I have strong coupling now, because on the one hand the forum view gets called inside HomeController, and on the other hand it will pretty much always
be used with ForumController from now on. So that might be unnecessary/wrong somehow?
edit: If I do this, the URLs change in a weird way, there must be a better solution right?
First when I click on forum link on main page, I'm at: /Home/Forum. I look at the forum, everything is fine.
Now I click on "Post a topic", and after the roundtrip I'm at /Forum/PostTopic. Home is gone.
If you have a ForumController its associated views need to be located at ~/Views/Forum.
For example:
public class ForumController: Controller
{
public ActionResult Index()
{
return View();
}
}
and then you would have the corresponding view in ~/Views/Forum/Index.cshtml:
#{
ViewBag.Title = "Forum";
}
<h2>Forum</h2>
<p>
Put content here.
</p>
and finally you generate a link to the Index action of the ForumController like this:
#Html.ActionLink("Go to forum", "Index", "Forum")