Hey, one more newbie here, just playing around with .NET MVC. My main task is to have a few semi-static pages on URLs like:
/about/
/about/contacts/
/about/jobs/
I'm using a controller for that called Static and have the following route attached:
routes.MapRoute(
"About",
"about/{id}",
new { controller = "Static", action = "Index", id = UrlParameter.Optional }
);
It seems to work fine as I have the Static controller with the Index method which uses a switch statement to identify which page has to be viewed. I use the RedirectToAction() function to call other actions of the Static controller in order to display pages with other views. My views are:
/Static/About.aspx
/Static/Contacts.aspx
/Static/Jobs.aspx
This method seems to work fine, but what I don't like about it is the redirect, so browsing to /about/contacts I get a redirect to /Static/Contacts which is not what I'd really like to see in the URL.
So my question is - what is the correct way of doing this? And is there a way to explicitly call a certain view from my Index action?
Thanks,
~ K.
Don't do the redirect. Instead of using a switch statement within the Index action, have a separate action for each page (ie. About, Contacts, Job) each with their own view.
Your Static controller could look something like this:
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
return View();
}
public ActionResult Contacts()
{
return View();
}
public ActionResult Jobs()
{
return View();
}
And if you needed to do any processing specific to Contacts or Jobs, it can be done within their respective actions.
To explicitly call a certain view:
return View("ViewName");
There are seven overloads for the View() method. A number of which allow you to pass the Model:
return View("ViewName", Model);
I'd recommend moving away from Static, and have an About controller. Within that controller, one method per page.
public ActionResult About()
{
return View ("About");
}
//Jobs() and Contacts() follow the same pattern
3 routes to match:
routes.MapRoute(
"Jobs",
"about/jobs",
new { controller = "About", action = "Jobs" }
);
routes.MapRoute(
"Contact",
"about/contact",
new { controller = "About", action = "Contact" }
);
routes.MapRoute(
"About",
"about/",
new { controller = "About", action = "About" }
);
you cant return views from a different controller and have the first controller in the URL.
the only way is use your about controller.
so place your logic in your about controller.
i have the same for myself in my Admin controller. it's just a page with some static links, and some extra pages.
in the index.aspx i have
<ul>
<li>
<%= Html.ActionLink("Evaluaties", "Evaluaties", "Admin")%></li>
<li>
<%= Html.ActionLink("ONAS aanbieders", "Index", "ONASAanbieder")%></li>
<li>
<%= Html.ActionLink("ONAS aanbod", "Index", "ONASAanbod")%></li>
<li>
<%= Html.ActionLink("Helpbox", "Index", "HelpBox")%></li>
</ul>
in the controller I have
public ActionResult Index() {
return View();
}
public ActionResult Evaluaties() {
return View();
}
this works like you described, no need to alter the routes.
obviously i have an Evaluaties.aspx in my Admin folder in the Views folder.
gives me this URL: http://localhost:50152/Admin/Evaluaties
Related
I am getting results based on an ID which is passed into the controller via the URL, for example Site/View/12 - this will bring back all results that match 12.
However, if there are no results, I want to re-direct back to the Index page which also has the search field.
public new ActionResult View(string ID = "")
{
XDocument xml = XDocument.Load(xmlPath);
var bikes = (xml).ToList();
if (!bikes.Any())
{
return RedirectToAction("Index", "Home");
}
else
{
return View(bikes);
}
}
However, whilst trying to view any page (/Add, /Index etc) I get a "This webpage has a redirect loop" error.
I'm not quite sure what's going on, because as far as I can tell viewing these pages shouldn't even trigger anything inside ActionResult View(). Also, the RedirectToAction is going to Index - so I cannot figure out where the loop is.
If I remove the line return RedirectToAction("Index", "Home"); the application functions normally.
Any advice would be very welcome, thank you.
(edit) Here's the Index controller:
public ActionResult Index()
{
return View();
}
And here's the RouteConfig.cs file:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
The controller has a View method to return the view, but your Action method is also named View, and that's where it gets stuck. Change your action to be:
[ActionName("View")]
public new ActionResult ViewItem(string ID = "")
And everything should work OK.
Your action is named View. When you do
public ActionResult Index()
{
return View();
}
it's defaulting to your method (the optional parameter makes it valid):
public new ActionResult View(string ID = "")
If you mouseover return View() intellisense will tell you which View() its calling. Rename your View action and you'll see that the intellisense changes which View() is referenced, and it should work fine. Using an attribute to keep your action as View seems like its just going to cause another confusing headache later.
I needed to get a data from the url on my post method. I have this routing on my asax:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Then on my Home Controller, under Get:
[HttpGet]
public ActionResult Index()
{
var id = ControllerContext.RouteData.GetRequiredString("id");
}
And on Post:
[HttpPost]
public ActionResult SomeNewNameHere(HomeModel homeModel)
{
var id = ControllerContext.RouteData.GetRequiredString("id");
}
My problem here is I need that id from the url on my post method. By debugging, I noticed that it gets the id on the get method, but when i post it, it returns me a null resulting to an error. So basically, RouteValues work on Get but not on my Post. Anything I missed here? Thanks!
Sample url:
http://localhost:1000/Controller/Action/12312121212
EDIT:
I also tried this but no luck:
var id = ControllerContext.RouteData.Values["id"];
The form on the view:
#using (Html.BeginForm("SomeNewNameHere", "Home", FormMethod.Post))
You can add id parameter to the post URL in your view:
#using (Html.BeginForm("SomeNewNameHere", "Home",new { id = Model.ID}, FormMethod.Post))
Add and int Id property to your HomeModel
then in your view, within your form:
#Html.Hiddenfor(m => m.Id)
This will post the Id to your action method
With the help of Ufuk Hacıoğulları, I came up with this solution on my form:
(Html.BeginForm("SomeNewNameHere", "Home",new { id = ViewContext.RouteData.GetRequiredString("id") }, FormMethod.Post))
So what happened here is it includes the id when it do a post.
Your Querystring values and Form values are automatically sent to the ActionResult at the same time, and the ASP.Net MVC Model binder will attempt to bind everything that it can.
So your GET Index ActionResult should be;
[HttpGet]
public ActionResult Index(int id)
{
// access id directly
}
And your POST Index ActionResult should be;
[HttpPost]
public ActionResult SomeNewNameHere(int id, HomeModel homeModel)
{
// access id directly
}
So your URL needs to be /Home/Index?id=1
I need my page names to have a dash in the name. E.G our-vision
I'm new to MVC & c# so I may be going about all this wrong.
Here is my controller:
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
//
// GET: /our-vision/
public ActionResult ourVision()
{
return View();
}
}
And then in my views, I have Views/Home/ourVision.cshtml.
When I compile and go to http://localhost/ourVision it works, but when I go to http://localhost/our-vision it does not.
Here is my routing:
routes.MapRoute(
"Default", // Route name
"{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
You'll need to do a few things in order to achieve that.
First, to achieve our-Vision, you'll need to give your action method the ActionName attribute, like so:
[ActionName("our-Vision")]
public ActionResult ourVision()
Next, you'll have to rename your ourVision.cshtml view to be our-Vision.cshtml
Finally, whenever you're using Url.Action or ActionLink, you need to use our-Vision and not vision, like so:
Url.Action("our-Vision", "Home");
IMHO
The best way to do this - is define new route in route engine:
routes.MapRoute(
"OurVision", // Route name
"our-vision", // URL with parameters
new { controller = "Home", action = "ourVision" } // Parameter defaults
);
I have created a controller called loginController.cs and i have created a view called login.aspx
How do I call that view from loginController.cs?
The ActionResult is always set to index and for neatness, I want to specify what view the controller uses when called rather than it always calling its default index?
Hope that makes sense.
You can customize pretty much everything in MVC routing - there is no particular restriction on how routes look like (only ordering is important), you can name actions differently from method names (via ActionName attribute), your can name views whatever you want (i.e. by returning particular view by name).
return View("login");
In the interest of actually answering the question.. you can add a route ABOVE your default route in Global.asax:
routes.MapRoute(
"SpecialLoginRoute",
"login/",
new { controller = "Login", action = "Login", id = UrlParameter.Optional }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
..although, without properly thinking through what you're trying to achieve (that being.. changing what MVC does by default) you're bound to end up with lots and lots of messy routes.
Your return the view from your controller via your Action methods.
public class LoginController:Controller
{
public ActionResult Index()
{
return View();
//this method will return `~/Views/Login/Index.csthml/aspx` file
}
public ActionResult RecoverPassword()
{
return View();
//this method will return `~/Views/Login/RecoverPassword.csthml/aspx` file
}
}
If you need to return a different view (other than the action method name, you can explicitly mention it
public ActionResult FakeLogin()
{
return View("Login");
//this method will return `~/Views/Login/Login.csthml/aspx` file
}
If you want to return a view which exist in another controller folder, in ~/Views, you can use the full path
public ActionResult FakeLogin2()
{
return View("~/Views/Account/Signin");
//this method will return `~/Views/Account/Signin.csthml/aspx` file
}
I am teaching myself asp .net mvc3.
I want to create a user account page which has 3 tabs in it - say YourAddress, YourPhotos and YourProfile.
The 3rd tab (YourProfile) has 2 more subtabs in it ... ChangeDetails and DeactiaveAccount.
They are all dynamic pages and therefore I want to keep them as separate pages.
Basically the urls would be:
localhost/MyHome/YourAddress
localhost/MyHome/YourPhotos
localhost/MyHome/YourProfile/ChangePassword
localhost/MyHome/YourProfile/DeactivateAccount
(As requested I have changed the generic tab1, tab2 etc to something in real-world scenario)
I am planning to do something like this:
public class MyHomeController : Controller
{
//
// GET: /MyHome/Tab1
public ActionResult Tab1()
{
return View();
}
//
// GET: /MyHome/Tab2
public ActionResult Tab2()
{
return View();
}
//
// GET: /MyHome/Tab3
public ActionResult Tab3()
{
return View();
}
}
How do I handle the subtabs of YourProfile? How do I call a controller within a controller?
What is the best way to accomplish this.
Thanks
Have separate action method for each tab item in your controller.
public class MyHomeController : Controller
{
public ActionResult YourAddress()
{
return View();
}
public ActionResult YourPhotos()
{
return View();
}
public ActionResult YouProfile()
{
return VieW();
}
public ActionResult ChangePassword()
{
return View();
}
public ActionResult DeActivate()
{
return View();
}
}
For the sub tab content, define that route in the global.asax
routes.MapRoute("ChangePass","YourProfile/ChangePassword",
new { controller="MyHome", action="ChangePassword" });
routes.MapRoute("DeActivate","YourProfile/DeActivate",
new { controller="MyHome", action="DeActivate" });
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
Always use Url.Action Html Helper method to render a path to an action method.
<div id="tabs">
<ul>
<li>Address</li>
<li>Photos</li>
</ul>
</div>