ASP.NET MVC 3 - Setting up routes - asp.net-mvc-3

I'm migrating an ASP.NET web forms application to ASP.NET MVC 3. I kind of understand routing, but I sort of don't. In my application, I have created three .cshtml files in the directory located at /internal/products/find/. For the sake of demonstration, those .cshtml files are named "view1.cshtml", "view2.cshtml", and "view3.cshtml".
I have a controller named "InternalController". My goal is to use InternalController for all of the locations inside the /internal path. I'm not sure if what I'm trying to do is allowed. I assume it is. Either way, at this time, I have the following in InternalController:
public ActionResult View1()
{
return View();
}
public ActionResult View2()
{
return View();
}
public ActionResult View3()
{
return View();
}
In my global.asax.cs file, I'm trying to register the routes to these views as follows:
routes.MapRoute(
"View1",
"{controller}/products/find/view1",
new { controller = "Internal", action = "View1" }
);
routes.MapRoute(
"View2",
"{controller}/products/find/view2",
new { controller = "Internal", action = "View2" }
);
routes.MapRoute(
"View3",
"{controller}/products/find/view3",
new { controller = "Internal", action = "View3" }
);
Whenever I try to visit /internal/products/find/view1 in my browser, I see the ASP.NET error screen and it says:
The view 'View1' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/internal/View1.aspx
~/Views/internal/View1.ascx
~/Views/Shared/View1.aspx
~/Views/Shared/View1.ascx
~/Views/dashboard/View1.cshtml
~/Views/dashboard/View1.vbhtml
~/Views/Shared/View1.cshtml
~/Views/Shared/View1.vbhtml
What am I doing wrong? The path /internal/products/find/view1 is the most important part for me. Ideally, I would like to expose that in InternalController everytime. But I'm having a rough go at it. What am I doing wrong?
Thanks!

When you write
routes.MapRoute(
"View1",
"{controller}/products/find/{action}",
new { controller = "Internal", action = "View1" }
);
it means that whenever user writes into his browser:
http://mysite.com/blahblah/products/find/blahblahview
it will activate action view1 inside controller blahblahview. But it doesn't mean that view1.cshtml file is at that path. Actually, asp.net mvc looks for views at directories defined by convention...and convetion is:
~/Views/ControllerName/ViewName
so, your view should be in a folder:
~/Views/Internal/View1.cshtml
Unlike ASP.NET WebForms you are used to, ASP.NET MVC is pretty much driven by naming conventions as you could probably see (you always name your controllers like BlahBlah*Controller*, you always place your views inside Views folder etc... Read some tutorials here and catch up with basics.

Related

Cannot view my new MVC 4 application

I just created a new basic MVC 4 application in VS 2010. I just clicked the play button to test it came up in the web browser and I'm getting the following page:
I think I need to change my virtual path to something but I don't know what.
EDIT: Can't see what it says properly in the picture:
Server Error in '/' Application.
--------------------------------------------------------------------------------
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /
If you created an Empty Project you will need to create a HomeController with an Index Action. You will also need to create a View in ~/Views/Home/ called Index.
The other project templates create this for you but the Empty Project does not.
public class HomeController : Controller
{
public ActionResult Index()
{
return View()
}
}
No one person gave me the full answer. So this is an amalgamation of #MattiVirkkunen and #BrettAlfred
Add this within RouteConfig.cs
routes.MapRoute(
name: "Default",
url: "",
defaults: new { controller = "Home", action = "Home" }
);
Add this within HomeController.cs
public ActionResult Login()
{
return View();
}
Kya Neeta MVC me neyi ho Kya?? I am too :)
I think u have created a start-up page in your applicaition.
Type Http: //localhost:8080/Home/Index in your url
http: //localhost:/ControllerName/ActionName
if that does not work please create a new MVC application from scratch.

ASP.NET MVC 3 won't recognise .cshtml view files

I have ported an mvc 3 app from vs 2010 to vs2012.
The ported app is using .NET 4.
All the old bits work, but with a new view, created in vs 2012, the view engine is not looking for .cshtml files for the view.
For example, when the user requests the index action on the Welcome controller in the Solicitors area, the url is:
mysite.com/solicitors/welcome/gg
(where gg is the user name). In that case, the error that comes back is:
The view 'Index' or its master was not found or no view engine
supports the searched locations. The following locations were
searched: ~/Areas/Solicitors/Views/Welcome/Index.aspx
~/Areas/Solicitors/Views/Welcome/Index.ascx
~/Areas/Solicitors/Views/Shared/Index.aspx
~/Areas/Solicitors/Views/Shared/Index.ascx ~/Views/Welcome/Index.aspx
~/Views/Welcome/Index.ascx ~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx ~/Areas/Solicitors/Views/Welcome/gg.master
~/Areas/Solicitors/Views/Shared/gg.master ~/Views/Welcome/gg.master
~/Views/Shared/gg.master ~/Areas/Solicitors/Views/Welcome/gg.cshtml
~/Areas/Solicitors/Views/Welcome/gg.vbhtml
~/Areas/Solicitors/Views/Shared/gg.cshtml
~/Areas/Solicitors/Views/Shared/gg.vbhtml ~/Views/Welcome/gg.cshtml
~/Views/Welcome/gg.vbhtml ~/Views/Shared/gg.cshtml
~/Views/Shared/gg.vbhtml
I have already added the following key to appsettings in web.config, but it makes no difference.
<add key="webpages:Version" value="1.0" />
EDIT:
Route in SolictorAreaRegistration.cs:
context.MapRoute(
"Solicitors_Welcome",
"Solicitors/Welcome/{nameUser}",
new { controller = "Welcome", action = "Index", nameUser = UrlParameter.Optional }
);
EDIT 2:
Using RouteDebug, I can see that the correct controller and action are found.
Route Data
Key Value
nameUser: gg
controller: Welcome
action: Index
Data Tokens
Key Value
Namespaces: System.String[]
area: Solicitors
UseNamespaceFallback: False
EDIT 3:
The route is found correctly, as I can see from debugging: the Index action is hit.
The problem happens when the line call the view is called:
namespace MyApp.Areas.Solicitors.Controllers
{
[Authorize]
public partial class WelcomeController : Controller
{
//
// GET: /Solicitors/Welcome/
public virtual ActionResult Index(string nameUser)
{
return View("Index", nameUser);
}
}
}
OK, got to the bottom of it:
The Problem:
The problem is that the model of my view is of type string. In my action, I was passing in a string as the model parameter:
public virtual ActionResult Index(string nameUser)
{
return View("Index", nameUser);
}
This will clash with one of the overloads of Controller.View(...):
View(string, string)
The second parameter expects the name of a layout file. When you do this, MVC goes off looking for a layout file with a name of the value of your string, which could be, for example:
"Hello, World. I'm an idiot, but if you give me a decent error message, I might be able to fix the bug."
Obviously, a layout file with that name doesn't exist. Nor does a layout file called "gg" either (my (test) solicitor's username).
The Solution:
The solution is simple:
Specify that the second parameter is the model, not the layout.
public virtual ActionResult Index(string nameUser)
{
return View("Index", model: nameUser);
}
Useful Article:
To view an extended discussion of this very issue, see the following article:
MVC Gotcha: Beware when using your view's model is a string
Many thanks to heartysoft.com for the enlightenment.
It is looking as you can see from the error message:
~/Areas/Solicitors/Views/Welcome/gg.cshtml
If you need to look for the Index view then you need to specify it:
http://mysite.com/solicitors/welcome/index/gg

Dynamic Routing in ASP.NET MVC 3

I am building a blog engine using MVC 3 and razor. In this scenario, I have given options like a user can have multiple blogs (similar to blogger.com)
Now say a user 'yasser' has the following 3 blogs
TechStory
GameGeek
MeMyStory
so I want all other users to access these blogs by the following urls
www.domainName.com/blogs/TechStory
www.domainName.com/blogs/GameGeek
www.domainName.com/blogs/MeMyStory
And more blogs can be added hence more such url will be acessed in future.
I know that something needs to be done with Routing, but being new to MVC dont seems to get it. Please can some one guide me on this.
Add this route on top of your Default one:
routes.MapRoute(
"Blog",
"Blogs/{blogName}",
new { controller = "Blogs", action = "Index" }
);
Your controller will look like this:
public class BlogsController : Controller
{
public ActionResult Index(string blogName)
{
BlogModel model = // find blog by blog name
return View(model);
}
}
Also, one suggestion: Keep your controller names in singular mode: BlogController instead of BlogsController. Change URL and Routing accordingly if you decide to do so.

ASP.NET MVC3 sample project removing home folder

I'm using the ASP.NET MVC3 sample project and would like to have new links added to the page that go directly to the root url
So instead of mydomain.com/Home/About it would do mydomain/About.
This page suggests adding a new route. http://weblogs.asp.net/gunnarpeipman/archive/2011/04/17/asp-net-mvc-defining-short-urls-for-root-level-pages.aspx
Is there another way? Say I have 5 pages that will be on the root do I have to add a special route for each one?
Under the assumption that you are looking to do a bunch of single path requests/respones, and not just redirect home controller actions, then this is an option.
The link you provide is one way to do that. The other is to create 5 controllers using the default route. I'm not sure if I would suggest either is better (due to a lack of what your 5 paths actually are), but they both produce the same out come. If your default route looks like:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index",
id = UrlParameter.Optional } // Parameter defaults
);
It's basically stating that the default controller is home and the default action is index. These values are not mutually inclusive, meaning that neither required the other in order to be a default value.
Thus you could do:
website.com/about with
public AboutController
{
public ActionResult index()
{
return this.View();
}
}
and/or website.com/people with
public PeopleController
{
public ActionResult index()
{
return this.View();
}
}

ASP.NET MVC3 Nested Resources within an Area

I come from a Rails background and I'm having problems wrapping my head around Microsoft's MVC framework.
Today it's Routing. Rails gives you namespaces (e.g. Admin) which is the equivalent of Areas in .NET MVC3. Rails also allows you to define nested resources within your routes that will give you for example /posts/1/comments/1/edit and in your action you basically get params[:post_id] and params[:id].
I need something similar in ASP.NET MVC3 but not sure how to go about this. Googling for this results in at least 30 different ways to accomplish this and non of them mention areas.
It feels like I should add/modify something within here:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
But not sure where. Any suggestions?
I think you're in the right file (your AreaRegistration.cs file). I prefer being a little more explicit with my routes rather than using the default 'catch all' type of route that they provide. So here's an example of how I'd handle this:
Add something like this before the existing route (or get rid of the existing one all together) in the RegisterArea method
context.MapRoute(
"Edit_Comment",
"posts/{postId}/comments/{commentId}/edit",
new { controller = "Comment", action = "Edit" }
);
Then in your CommentController.cs you would have the following action:
public ActionResult Edit(int postId, int commentId)
{
// Do your edit logic then return an ActionResult
}

Resources