I know there are a lot other topics like this, but from what I found, and did accordingly to the answers - I still have the error.
The Global.asax:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Func", action = "Main", id = UrlParameter.Optional } // Parameter defaults
);
The Controller:
public class FuncController : Controller
{
//
// GET: /Func/
public ActionResult Main()
{
return View();
}
public ActionResult Products()
{
return View();
}
And accordingly the 2 .cshtml View files with the Main and Products names.
In the "Project Properties->Web" I selected "Start URL" with value "http:// localhost:63497/Main". I don't get it where might the problem be, as in the other topics I found about this error, the problem was always in some of these things. But now, everything seems to be fine, and still - error.
Main is the Action method. You need to navigate to the Controller and let that hit the appropriate Action. Try navigating to:
http:// localhost:63497/Func/Main
Which is Func Controller. ActionMethod Main
try like this..
http://localhost:63497/Func/Main.
because the route is from controller to ActionResult.
so, here Func is the Controller and the Main is your ActionResult Method.
so, you have to use the controller first in url before the Action Method.
Related
I am learning asp.net MVC and I was trying Redirect to action and I tried the following code and I keep getting Redirect Loop Error.
This is the Controller class in which I am getting an error
public class CuisineController : Controller
{
// GET: Cuisine
public ActionResult Search(string name)
{
return RedirectToAction("About","Cuisine");
}
public ActionResult Index()
{
return Content("This is Index");
}
public ActionResult About()
{
return Content("this is About");
}
}
I have also created a route of my own other than the Default route
routes.MapRoute(name: "Cuisine",
url: "cuisine/{name}",
defaults: new { controller = "Cuisine", action = "Search", name = UrlParameter.Optional });
When I try to access the Cuisine controller it gives me a redirect loop error.
Thank you
In your routeConfig, you have a route defined for "cuisine/{name}" and it will be sent to the Search action method.
In your Search action method, You are redirecting to the About, Which is cuisine/About. This is matching with the route you defined cuisine/{name} so it will send the request to Search action again. The same process will keep running. That is why you are getting the redirect loop
You should either delete this specific route you defined or rename the url pattern for cusine search to prevent the redirect loop.
routes.MapRoute(name: "Cuisine",
url: "searchcuisine/{name}",
defaults: new { controller = "Cuisine", action = "Search",
name = UrlParameter.Optional });
This should be pretty obvious:
routes.MapRoute(name: "Cuisine",
url: "cuisine/{name}",
defaults: new { controller = "Cuisine", action = "Search", name = UrlParameter.Optional })
Says all urls that start with cuisine/ use the Search method on the CuisineController.
/Cuisine/About starts with that url, so it willl always use the Search method.
It looks like you want to make {name} part of URL. You can use attribute routing instead of changing default routing, it does not have such global "destructive" effects (explained in other answers) at least, and looks it's what you are actually after :)
[Route("Search/{name}")]
public ActionResult Search(string name)
{
return RedirectToAction("About", "Home");
}
See more about attribute routing here (for this to work, don't forget to add routes.MapMvcAttributeRoutes() if it is not there yet).
You need to restore controller action pattern. Just change url: "cuisine/{name}" to url: "cuisine/{action}/{name}"
I have 2 actions in one controller
public ActionResult DoSomething()
{
...
}
public ActionResult SoSomethingAgain()
{
...
}
I would like to have both requests go to the same action.
perhaps an alias....
[ie. SoSomethingAgain]
public ActionResult DoSomething()
{
...
}
What is the proper approach?
If I'm reading this correctly you can just do:
public ActionResult DoSomething()
{
...
}
public ActionResult SoSomethingAgain()
{
return DoSomething();
}
In SoSomethingAgain just do this:
return DoSomething();
The only other option you have would be to build a specific Route for that controller when you setup routes at the start of the application. That's going to be a lot more work than it's worth.
If SoSomethingAgain is the called action then the two earlier answers will run the code that is inside DoSomething, but the controller action and context is still SoSomethingAgain. This means that a return View() statement inside the DoSomething would look for a SoSomethingAgain view.
Similarly the pipeline would use filters defined on SoSomethingAgain, and not those on DoSomething. You can see this if you put an [Authorize] filter on DoSomething. If you hit the DoSomething action you will be prompted to log in, but if you hit the SoSomethingElse action you will not be prompted.
Maybe that's what you want, maybe not. If it isn't and you want to have both a DoSomething url and a SoSomethingElse url, but both running the same code, then get rid of the SoSomethingElse controller action, and add a custom route (before the default route).
routes.MapRoute(
name: "SoSomethingAgainRoute",
url: "{controller}/SoSomethingAgain/{id}",
defaults: new { controller = "Home", action = "DoSomething", id = UrlParameter.Optional }
);
I am familiar with CodeIgniter so I'm not a newbie, but I sure feel like one as I move to MVC using C#/.NET. I would expect calling the below controller would properly bind the slash-delimited arguments of URL to the controller input params. Eg: I would expect http://localhost/Download/51 to give fileID=51. However, when I run this, fileID is null when controller is called. Either HttpGet needs querystring with ? and & or need to modify routes somehow to bind properly. Help, please?
[HttpGet]
public ActionResult Download(String fileID)
{
....// http://localhost/Download/51
}
Either use id which is the default route parameter name configured in your Global.asax:
[HttpGet]
public ActionResult Download(string id)
{
....// http://localhost/Download/51
}
or change your routing configuration so that fileID is used:
routes.MapRoute(
"Default",
"{controller}/{action}/{fileid}",
new { controller = "Home", action = "Index", fileid = UrlParameter.Optional }
);
Also checkout the following for more details on routing.
We just started using ASP.NET MVC3 and we want to unit test our controller.
Here is my controller function:
[HttpGet]
Public ActionResult Action()
{
Guid Id = Guid.Empty;
string[] UrlSegments = Request.Url.Segments;
Guid.TryParse(UrlSegments[UrlSegments.Count() - 1], out Id);
if(Id == Guid.Empty)
return RedirectToAction("ErrorPage");
}
I want to test this controller function.I have put the matching route to match this function in my global.asax file. Basically I am trying to retrieve the guid from the URl and if it is not good then take him to error page.
HttpRequestBase class URl is no setter,so I am confused how to test this functionality?
As for testing read the link provided in the comments above but I would recommend doing some reading on MVC Routing or here, it does exactly what you are trying to achieve.
Have a look in your global.ascx.cs file you will find something like this:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
This is the out of the box route for the MVC framework.
Routes will match a url based on the convention you give them.
So based on the default route above and given a url like this:
http://localhost:portnumber/MyController/MyAction/8B4B93DE-76CA-4552-B4AA-460400761EAD
It will try and match this url to a controller called MyController with an action called MyAction, which receives and Id. It will only hit this action if all the criteria match.
If there is no id in the URL and id defined on your action method is not a nullable type then it simple wont execute. It will rather try match another Url, if it cant find one it will give a 404.
Like this:
public class MyController : Controller {
[HttpGet]
Public ActionResult MyAction(Guid id)
{
}
}
At the moment I have 3 controllers: Home, Summary and Detail
However, each has only one action: Index, Display and Display respectively.
This smell bad to me.
I was hoping to use the MapRoute to allow:
myapp/Home
myapp/Summary/prop1/prop2
myapp/Detail/prop1/prop2/prop3
instead of
myapp/Home
myapp/Summary/Display/prop1/prop2
myapp/Detail/Display/prop1/prop2/prop3
and thereby miss out the "Display" part...but again, this doesn't smell right. Although it works, it means manually adding links instead of using Html.ActionLink(...)
Would it be better to have Home/Index, Home/Summary and Home/Detail all in one controller?
I was hoping to provide a simple URL structure so users who know what they are doing could simply type it in as above...the "Home" part seems wasted?
I agree with #Tim that you should use a single controller. A controller is a logical grouping of actions; for example the CRUD operations for Foo. NerdDinner is a good example of this.
I disagree with the routes. You can do whatever you want with the routing; but it should be meaningful to the user. You probably just have a single catchall route similar to the one below.
routes.MapRoute("Default", //RouteName
"{controller}/{action}/{id}", //RouteUrl
new { //RouteDefaults
controller = "Home",
action = "Index",
id = UrlParameter.Optional}
)
You can have the routes you want by using a single controller.
Your desired urls:
myapp/Home
myapp/Summary/prop1/prop2
myapp/Detail/prop1/prop2/prop3
The controller setup:
public class HomeController : Controller
{
public ActionResult Index() { ... }
public ActionResult Summary() { ... }
public ActionResult Details() { ... }
}
The routing setup:
routes.MapRoute("Home-Index", //RouteName
"myapp/Home", //RouteUrl
new { //RouteDefaults
controller = "Home",
action = "Index"});
routes.MapRoute("Home-Summary", //RouteName
"myapp/Summary/prop1/prop2", //RouteUrl
new { //RouteDefaults
controller = "Home",
action = "Summary",
prop1 = UrlParameter.Optional,
prop2 = UrlParameter.Optional});
routes.MapRoute("Default", //RouteName
"{controller}/{action}/{id}", //RouteUrl
new { //RouteDefaults
controller = "Home",
action = "Index",
id = UrlParameter.Optional}
)
Now there are a few important things to note:
Routing works like a switch statement, the first url that matches is
the one it will use, that's why you have the catchall as the last
one.
The url defined in your map route can be whatever you want. It
doesn't have to match with the controller, because once you remove
the placeholders ({controller}, etc) it uses the default for
navigation. So the Home-Index route url could be myapp/foo/bar/baz
and id would still take you to the Home index action.
The placeholders work automagically. I have not been able to find a good resource explaining how the default route works.
Hope this helps.
Not sure if I totally get your question, but what about creating a base controller class that inherits from Controller, and have your shared actions there instead? That way you don't need to repeat yourself as much.
You need only one controller and inside it multiple actions..
public class HomeController : Controller
{
public ActionResult Index()
{
}
public ActionResult Summary()
{
}
public ActionResult Details()
{
}
}
In the action link
#Html.ActionLink("Details", "Details","Home");
that's enough, no need to add multiple controller..
Hope these helps..
You can pretty much go down any route you want when it comes to this, all just depends on what you want to achieve.
You can stick all the actions in the Home controller so your routes would be
myapp/Home
myapp/Home/Summary/prop1/prop2
myapp/Home/Details/prop1/prop2/prop3
In this option you have 1 controller, 3 actions, with 2 additional routes to handle the URls
It depends on what the summary and details are of though? Like if it is the summary of an order, i would prefer
myapp/Orders/Summary/prop1/prop2
myapp/Orders/Details/prop1/prop2/prop3
In this you would have your Home controller and the Index action, then an Orders controller with two actions. I would say that Summary and Details would generally suggest that you are displaying something anyway, so you would not need the "Display" part as you have in your suggestions.
If you want your URLS to be
myapp/Home
myapp/Summary/prop1/prop2
myapp/Detail/prop1/prop2/prop3
Then you make 3 controllers
HomeController
SummaryController
DetailController
Each of these will have 1 Action
public ActionResult Index() {
}
For the SUmmary and Detail controller you will just pass in some extra paramaters to the Index action