How exactly does one render a .cshtml file?
I'm new to ASP.NET. I've created an MVC project using Visual Studio's template. Apparently all the templates have .cshtml for the Default / Index files. But my server gives me this error when I try to view it:
Server Error in '/' Application. This type of page is not served.
Description: The type of page you have requested is not served because it has been explicitly forbidden. The extension '.cshtml' may be incorrect. Please review the URL below and make sure that it is spelled correctly.
Requested URL: /mobile/WebApplication1/Index.cshtml
So, how exactly do I view the Index file? Do I need to pass it through something to convert to .html or render it somehow?
Files with extension .cshtml in the context of ASP.NET MVC are views. They cannot be viewed (served by the web server) just by themselves. You need a controller action that will render the view.
NOTE: you could employ some "tricks" to modify IIS settings and your app to enable serving .cshtml files to browser requests, but this would not be normal behaviour.
Assuming your view is located at ~/Views/Index.cshtml here is a (trivial) example of a simple controller action:
public class ExampleController : Controller
{
public ActionResult Index()
{
return View();
}
}
This controller should be placed at: ~/Controllers/ExampleController.cs
You will access the rendered page at: localhost/example/index
More about ASP.NET MVC here: http://www.asp.net/mvc/overview/getting-started/introduction/getting-started
You can not access an MVC view directly by its name. Ever...!
What you can do is call a Controller action, and that is done through an URL such as /WebApplication1/Index.
The above URL means two things:
there has to be a class called WebApplication1Controller.cs,
and that class must have a method public ActionResult Index().
The method Index will then determine which View (if any) is going to be displayed, and also what data will be sent to that view to use.
If the method Index executes return View(); then there is an implicit rule that the view with the same name (in this case Index.cshtml) is going to be shown.
Or if for some reason Index executes return View("Wow"); instead, then the view called Wow.cshtml will be displayed.
Related
I have some partial actions that I render with the Asp.Net Futures RenderAction method. Some of these perform redirects after the forms in them have been processed.
Now that I upgraded to Asp.Net MVC 2 RC it gives me an error "Child actions are not allowed to perform redirect actions".
I checked out the source code and I found the line that throws the exception. To Get around it I can make a custom RedirectResult, But before I do I want to understand why the framework doesn't allow it in the first place. There must be a good reason and maybe I Shouldn't do either.
Any one know the reason for this limitation?
Thanks
The limitation exists because MVC has already started rendering a view to the client. The effect of redirecting from this point is undefined. It could work perfectly, it could continue rendering the original view without redirecting, it could throw a different exception, etc.
Since the result of performing this action is undefined, the framework blocks it. In practice, RenderAction should never be used to render anything other than a view (or view-like content) for similar reasons.
In your particular case, the outer action should redirect. If you're just going to end up redirecting from within the view anyway without showing anything to the user, then there was really no purpose to going through the view in the first place, as the outer action could have delegated the work appropriately on its own.
Try to use something like this in Child Action:
ControllerContext.HttpContext.Response.Redirect(ControllerContext.HttpContext.Request.Url.ToString());
My solution.
Action method:
return View("Redirect", model);
View:
<script type="text/javascript" language="javascript">
document.location = '<%: Url.Action("Index", "Album", new { id = Model.Id }) %>';</script>
In my case, the form being rendered is a "configure" panel on an extension to a website I'm building. I'd like the extension's own controller to be able to handle the form processing and then redirect back to the admin page listing all configured extensions. I don't think it's appropriate or practical here to ask the parent page's controller to process the form for the extension. What would you suggest I do instead?
In my unusual case, I had a custom AuthorizeAttribute attached to my controllers which was attempting to redirect on a child action, which is (as mentioned above) not allowed.
To resolve the issue, I removed authorisation checking redirection on all child actions:
Public Overrides Sub OnAuthorization(filterContext As AuthorizationContext)
//Child actions cannot redirect anyway, so no need to check permissions.
If filterContext.IsChildAction Then Exit Sub
.. parent authorisation checks ..
Sometimes this error occured when you try to render an action of base action result.
Example:
ActionResult X
Return View
View X
RenderAction Y
ActionResult Y
// Bla bla
return View
// else
return RedirectToAction X
In that case just point the partial view form's submit url to action that was the target of your problematic redirection and let it perform itself redirection to its GET version.
I'm developing an application using MVC 5. I have added a new area which contains a view called Register and gradually adding content to it. For debugging purposes, I'm trying to access that area directly through url after logging in to application. I'm using the url: http://localhost:port/Area/Account/Manage/Register
But I'm getting error. How will be the url, If need to view Register page directly. Please find the directory structure below:
You cannot access the view file directly. You should access it via an action method.
Create an action method called Register in your ManageController (if not exists) and return the view
public ActionResult Register()
{
return View();
}
now you can access this by navigating to yoursitename/account/manage/register assuming you haven't altered the default route registration for the area.
This is a basic question about the routing machinery. From a new MVC project, I have this in the HomeController:
public ActionResult MyPage()
{
return View();
}
In the Views\Home folder, I have MyPage.aspx. The routing is still the default of {controller}/{action}/{id}. When I type in http://localhost:1790/Home/MyPage, it is correclty routes to MyPage.aspx. Since I haven't said anything about which view to render, how does ASP.NET MVC know to correctly route to MyPage.aspx? Looks as though the ActionResult name can also be used as the View/aspx page name...unless there is something I misunderstand in how the routing works. I can see how I end up in the Home folder, since the controller name corresponds to the View sub folder name. But does the Action name also correspond to the aspx name?
Would that work if the page was a PHP?
ASP.NET MVC subscribes to what is known as the Convention over Configuration paradigm whereas if you follow their conventions, basic things such as routing concerns will happen for you. But they also allow you to configure them if desired.
MVC implicitly assumes that if you return just View(), that you want View("MyPage") (i.e. the action name). No sense in repeating yourself unnecessarily.
It won't find a PHP file by default, but I'm sure you could override that behavior if you really wanted to. I can't imagine a sane scenario where you would be mixing PHP and ASP.NET MVC, but who knows :)
Action name is the same as the view / partial view name.
asp.net mvc doesn't work with php as far as I'm aware.
As has already been stated, ASP.NET MVC uses convention over configuration. Out of the box, your folder structure is something like this (only showing relevant portions and doing it from memory so...)
Site Root
+ Controllers
HomeController.cs
AccountController.cs
+ Views
+ Home
Index.aspx
+ Account
Index.aspx
+ Shared
The default routing handler is something similar to the following:
"{controller}/{action}/{id}"
There are default values for the route, but if you have a url that is a/b/c, it will look for action a on controller aController and pass it c as a parameter if said method on the controller accepts parameters.
A couple of things about that then need to be clarified. Again, convention over configuration:
1) All controller classes must end with Controller if you're using the default engine. That way, when a request comes in and the {controller} value is parsed, the engine adds Controller to it, looks in the Controller folder (and, thus, namespace), and locates the class.
2) By default -- this can be changed -- all views for a controller must reside in the Views/{controller} folder or in the Views/Shared folder.
3) Public methods on a controller are, by default, actions. You can hide this with an attribute to make themethod unavailable to the engine, but by default they are public.
So, when a request comes in the route is compared against all known routes (global.asax) and the first route that matches the request is accepted. The route is then parsed into the component parts to determine the controller, action, and parameters for the action.
Once the controller is identified, the engine instantiates an instance of that controller and executes the matching method (action) should it be found.
The action will return an ActionResult. View is an extensino method that actually returns ViewResult (if I remember that correctly). The default view for an action is a view of the same name as teh action residing in the Views/{ControllerName} folder.
Routing is a beast unto itself and I'd recommend a good bit of reading on it if you're going to play with it. Minutes to understand but a lifetime to master sorta thing.
To my knowledge, BTW, there is no engine that will use a php page as a view for a controller action.
I have some partial actions that I render with the Asp.Net Futures RenderAction method. Some of these perform redirects after the forms in them have been processed.
Now that I upgraded to Asp.Net MVC 2 RC it gives me an error "Child actions are not allowed to perform redirect actions".
I checked out the source code and I found the line that throws the exception. To Get around it I can make a custom RedirectResult, But before I do I want to understand why the framework doesn't allow it in the first place. There must be a good reason and maybe I Shouldn't do either.
Any one know the reason for this limitation?
Thanks
The limitation exists because MVC has already started rendering a view to the client. The effect of redirecting from this point is undefined. It could work perfectly, it could continue rendering the original view without redirecting, it could throw a different exception, etc.
Since the result of performing this action is undefined, the framework blocks it. In practice, RenderAction should never be used to render anything other than a view (or view-like content) for similar reasons.
In your particular case, the outer action should redirect. If you're just going to end up redirecting from within the view anyway without showing anything to the user, then there was really no purpose to going through the view in the first place, as the outer action could have delegated the work appropriately on its own.
Try to use something like this in Child Action:
ControllerContext.HttpContext.Response.Redirect(ControllerContext.HttpContext.Request.Url.ToString());
My solution.
Action method:
return View("Redirect", model);
View:
<script type="text/javascript" language="javascript">
document.location = '<%: Url.Action("Index", "Album", new { id = Model.Id }) %>';</script>
In my case, the form being rendered is a "configure" panel on an extension to a website I'm building. I'd like the extension's own controller to be able to handle the form processing and then redirect back to the admin page listing all configured extensions. I don't think it's appropriate or practical here to ask the parent page's controller to process the form for the extension. What would you suggest I do instead?
In my unusual case, I had a custom AuthorizeAttribute attached to my controllers which was attempting to redirect on a child action, which is (as mentioned above) not allowed.
To resolve the issue, I removed authorisation checking redirection on all child actions:
Public Overrides Sub OnAuthorization(filterContext As AuthorizationContext)
//Child actions cannot redirect anyway, so no need to check permissions.
If filterContext.IsChildAction Then Exit Sub
.. parent authorisation checks ..
Sometimes this error occured when you try to render an action of base action result.
Example:
ActionResult X
Return View
View X
RenderAction Y
ActionResult Y
// Bla bla
return View
// else
return RedirectToAction X
In that case just point the partial view form's submit url to action that was the target of your problematic redirection and let it perform itself redirection to its GET version.
Are there any good examples of mvc routing wherein every 404 page not found request is routed to a standard view in MVC which basically pulls the content from the database.
Just add this route to the bottom of your RouteTable:
routes.MapRoute("DynamicPages", "{*page}", new { Controller = "DynamicPages", Action = "Show", Page = String.Empty });
And create a controller for displaying dynamic pages from db:
public class DynamicPagesController : Controller
{
public ActionResult Show(string page)
{
var pageContent = DB.GetContentForPage(page);
return Content(pageContent);
}
}
Here's one way to do this: In your global.asax file in Application_Start, you need to set the default controller factory. Override it with an instance of your own factory.
void Application_Start()
{
ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
}
MyControllerFactory should inherit from DefaultControllerFactory and when selecting the controller to use, look in your database for the appropriate page you want to display. If the page exists, select the appropriate controller and override the action in the requestContext.RouteData collection to point at the appropriate action for displaying dynamic pages.
If the requested page doesn't exist, pass back a call to the base method and let it do what it would normally do.
There are other ways you could do it, but this one should work and allows you to intercept the request before you hit the 404 page.
modify the web.config file, you may Reference to this page and look at the setting custom error pages in web.config section.