Edited the question as I've found out that the issue isn't inside the razor, but instead in the route
I have a very simple login form, but somehow, when the user presses Login the page goes tot Error404 and it simply does not hit the controller breakpoints for some reason.
#using (Html.BeginRouteForm("MyCustomRoute", new { controller = "login", action = "verify", FormMethod.Post }))
{
<fieldset class="clearfix">
<p><span style="float:none;color:black; font-size:20pt;"></span></p>
<p><span style="float:none;color:black; font-size:20pt;"></span></p>
<p><span class="fa fa-user"></span>#Html.TextBoxFor(m => m.UserName, new { #class = "form-control", placeholder = "Username", onkeydown = "convertTabtoEnter(this, event)", autofocus = "" })</p> <!-- JS because of IE support; better: placeholder="Username" -->
<p>
<span class="fa fa-lock"></span>#Html.PasswordFor(m => m.Password, new { #class = "form-control", placeholder = "Password", onkeyup = "convertTabtoEnter()" })
</p> <!-- JS because of IE support; better: placeholder="Password" -->
<div>
<span style="width:48%; text-align:left; display: inline-block;">
<a class="small-text" href="#">
#*Forgot
password?*#
</a>
</span>
<span style="width:50%; text-align:right; display: inline-block;"><input type="submit" value="Sign In"></span>
</div>
</fieldset>
<div class="clearfix"></div>
}
And Inside my login controller I have a simple ActionResult named Verify with the 2 params.
[RoutePrefix("Login")]
public class LoginController : Controller
{
// GET: Login
public ActionResult Index()
{
return View();
}
[HttpPost]
[Route("Verify")] //Matches GET login/verify
public ActionResult Verify(string username, string password)
{...}
What exactly am I doing wrong here? It's not like this is rocket science.
Edit2:
I've noticed that whenever I change the RouteConfig.cs back to default it works correctly. So, the problem isn't inside the form tags but within the routings.
So I've been trying to add a custom route in order to get this working using this sample: Using Html.BeginForm() with custom routes
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "TrailersOverview",
url: "{TrailersOverview}/{action}/{vendid}",
defaults: new { controller = "TrailersOverview", action = "Index", vendId = UrlParameter.Optional }
);
routes.MapRoute(
"MyCustomRoute", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "login", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
name: "Default",
url: "{*anything}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
}
}
When I remove the routings and I simply bring everything back to default, the controller does get hit. Unfortunately I really need those routings for the rest of the app :(
There are several things that seems to be wrong:
Your Controller is missing in the route Config.
Action and Controller names are in wrong order.
RouteConfig:
A default route looks like that:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}/",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Form:
If you want to use Tag Helpers, then you have to change your code from:
<form action="#Url.Action("Login", "Verify")" method="post">
to:
<form asp-controller="Login" asp-action="Verify" method="post">
Have a look here.
#using (Html.BeginForm("Verify", "YourControllerName", FormMethod.Post))
{ your form here // }
please try this if it works !
One more thing add name attribute in your input fields which should be similar to the property name in your model like
#Html.TextBoxFor(m => m.UserName, new { #class = "form-control", id="username", name="USERNAME"})
And this USERNAME should be there in your model like:
Public class yourModel{Public string USERNAME{get;set;}}
And use your Model Object in your Action Method to fetch data.
Your custom route (the second in your RegisterRoutes code above) seems to be incorrect... based on what you stated above, it can/should be this:
routes.MapRoute(
"MyCustomRoute", // Route name
"Login/Verify", // (No parameters needed)
new { controller = "Login", action = "Verify" } // Parameter defaults
);
With this setup, alter the first line of your razor code to be this:
#using (Html.BeginRouteForm("MyCustomRoute", FormMethod.Post }))
{
<fieldset class="clearfix">
...
}
Using Html.BeginRouteForm will automatically use the defaults specified in your custom route; no need to add the defaults in Razor. Using FormMethod.Post as the second parameter will render your form's method as a POST.
Edit:
Let's fix your general Route problem. You're attempting to use Attribute Routing, which is described well here: https://www.dotnettricks.com/learn/mvc/understanding-attribute-routing-in-aspnet-mvc. I'd contend that it isn't necessary here.
First, fix your default Route (last route in your RegisterRoutes code) like so:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
// Change the 'controller' and 'action' parameters here to point to the Main page in your application.
Your default Route is very important, and should be configured as a catch-all for any requests can be simply mapped to a Controller/Action combination. I suspect that you experienced problems because your default Route was altered.
Next, comment out the Route and RoutePrefix attributes in your Login Controller... there's hardly a need for the [Route("Verify")] directive if you're using 'RegisterRoutes' properly.
// [RoutePrefix("Login")]
public class LoginController : Controller
{
// GET: Login
public ActionResult Index()
{
return View();
}
[HttpPost]
// [Route("Verify")] //Matches GET login/verify
public ActionResult Verify(string username, string password)
{...}
}
Now that the default Route is set up properly, the url '/Login' should take you to your Login screen, because the default action is "Index" (it's the default in your default Route above.)
Try adding routes.LowercaseUrls = true; to your route config as you seem to prefer lower-case versions of routes:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.LowercaseUrls = true;
routes.MapRoute(
name: "TrailersOverview",
url: "{TrailersOverview}/{action}/{vendid}",
defaults: new { controller = "TrailersOverview", action = "Index", vendId = UrlParameter.Optional }
);
routes.MapRoute(
"MyCustomRoute", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "login", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
name: "Default",
url: "{*}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
}
}
And for the default route, I think you wanted to mention {*} for url to match everything else?
Related
I suspect someone will call this a duplicate....I have looked through the examples that I have seen and tried to implement the suggested changes but I am still having this issue. In my index view, I have an ActionLink HTML Helper to redirect to an Edit. When I mouse over it, it shows the URL target as:
http://localhost:58028/Instruments/Edit?InstrumentId=1
Instead of the desired
http://localhost:58028/Instruments/Edit/1
I have built a "for comparison" scaffolded situation and it appears to me that I am doing the exact same thing, yet it is resulting in the proper URL. When I debug and stop in the Edit routine of the controller, it shows me that it is using the correct (and only) mapping.
Can someone please tell me what I am missing:
Here's my View code:
<td>#Html.ActionLink(item.Description, "Edit", new { InstrumentId = item.InstrumentId })</td>
Here's my Controller code:
public ActionResult Edit(int? InstrumentId)
and here's my routing:
public static void RegisterRoutes(RouteCollection routes)
{
//routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Your default route expects a parameter named id, so to use the default route, change the link to
#Html.ActionLink(item.Description, "Edit", new { id = item.InstrumentId })
and the method to
public ActionResult Edit(int? id)
or create a specific route for your method that includes a placeholder for a parameter named InstrumentId and place it before the default route
routes.MapRoute(
name: "InstrumentEdit",
url: "Instruments/Edit/InstrumentId",
defaults: new { controller = "Instruments", action = "Edit" }
);
routes.MapRoute(
name: "Default",
....
Both options will generate ../Instruments/Edit/1
try changing the Html Helper to this
#Html.ActionLink(item.Description, "Edit", new { id = item.InstrumentId })
Question background:
I'm trying to pass an variable - in this case an int 'productId' variable' in the url to a controller and action method specified in the ActionLink method.
The issue:
My routes are set as follows:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Login", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "ProductDetailHandler",
url: "{controller}/{action}/{productId}",
defaults: new { controller = "Product", action = "ProductDetail", productId = UrlParameter.Optional }
);
My 'ActionLink' in my 'Products.cshtml' view - which is returned by a controller called 'HomePageController' is set as follows:
#Html.ActionLink("Product", "ProductDetail", new { productId = (ViewBag.data as List<LoginTest.Models.HomePageItem>).First().Id })
The controller that receives the passed 'productId' along with its action method is set as follows:
public class ProductController : Controller
{
public ActionResult ProductDetail(int productId)
{
//logic
return View();
}
}
This is the issue, when looking at the URL it is shown to be redirecting to the 'HomePage' controller:
If someone could tell me why my ActionLink is not going to the Product controller that would be great.
EDIT:
This is the 'Homepage' view that I click a button to redirect me to 'product/productDetail/productId'
My route now just features the 'Default example':
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Login", id = UrlParameter.Optional }
);
The Action Link is now:
#Html.ActionLink("Product", "ProductDetail", "Product", new { id = (ViewBag.data as List<LoginTest.Models.HomePageItem>).First().Id })
The 'Product/ProductDetail' controller and action method now looks like:
public class ProductController : Controller
{
public ActionResult ProductDetail(int id)
{
string hold;
return View();
}
}
This still is giving me the the incorrect URL, as shown, note the 'productId' is now showing as 'length'?
Since the link is on a page rendered by HomePageController the default is to use that controller in the route. You need to use the overload that accepts a controller name
#Html.ActionLink("Your link text", "ProductDetail", "Product", new { id = 1 }, null)
As a side note, your original route table would have created /Product/ProductDetail?productId =1 with this overload because it matches the default route which is the first route in your table (the order of routes is important). In order to have /Product/ProductDetail/1, either reverse the order of the routes or just change the parameter of ProductDetail to int id rather than int productId
Make sure you are using an overload that has controllerName in it, as shown in the following screenshot.
When I remove routeValues: null, it uses a different overlaod which has routeValue as third paramater.
Try this:
routes.MapRoute(
name: "ProductDetailHandler",
url: "Product/{action}/{productId}",
defaults: new { controller = "Product", action = "ProductDetail", productId = UrlParameter.Optional }
);
routes.MapRoute
(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Not sure what you are trying to do with the Login controller. Maybe you can put log-in on your Home page or redirect the Home/Index to Login.
Also you can specify the default namespace if it doesn't find your controller:
routes.MapRoute(
name: "ProductDetailHandler",
url: "Product/{action}/{productId}",
defaults: new { controller = "Product", action = "ProductDetail", productId = UrlParameter.Optional },
new string[] { "MyProject.Controllers" }
);
routes.MapRoute
(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new string[] { "MyProject.Controllers" }
);
So, I am trying to submit a form on a List Page(http://example.com:3480/List) which is actually a Search implementation. So far I have done this:
index.cshtml
#using(Html.BeginForm("Search","ListController"))
{
<input id=query type=text name=query />
<input id=btnsearch type=submit value=Search />
}
ListController.cs
[HttpPost]
public ActionResult Search(FormCollection collection)
{
Response.Write("We are here");
// Get Post Params Here
string var1 = collection["query"];
Response.Write(var1);
return View();
}
Global.asax
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Details",
"Details/{id}/{orderid}",
new { controller = "Details", action = "Index", id = UrlParameter.Optional, orderid = UrlParameter.Optional }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional} // Parameter defaults
);
}
Upon Clicking it goes to http://example.com:3480/ListController/Search which seems fine.
Now I guess I need to define route in Global.aspx but not sure. What I want is to show result in same View file instead of creating a new one.
At this moment I am unable to get into Search method after POSTing form
Assuming you are currently just using the default route, the reason you are not reaching the action method is that the "Controller" suffix on your route is implicit - it shouldn't be part of your URL.
#using(Html.BeginForm("Search","List"))
Additionally, regarding:
What I want is to show result in same View file instead of creating a new one.
You can easily return a specific view from any controller action by specifying the name of the view in the call to the View method:
return View("Index");
I am developing an application in asp.net using mvc4. I am very new to asp.net. Following is my global.asax code
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Default", action = "Index",
id = UrlParameter.Optional }
);
}
Also
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
Also I am having a controller named Default1Controller, which has a action method named MyAction. On the click of button I want this Method to get executed. But while debugging the control does not come here i.e the method does not gets invoked. Following is my controller code
public class Default1Controller : Controller
{
//
// GET: /Default1/
public ActionResult Default1()
{
return View();
}
public ActionResult MyAction()
{
return View();
}
}
Also following is the cshtml
#{
ViewBag.Title = "Default1";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Default1</h2>
<div>
<p>Welcome to the world of MVC!!!!</p>
<div>
<input type="button" value="Click Me"
onclick="window.location.href('#Url.Action("MyAction","Default1Controller")')" />
</div>
</div>
On clicking on the button, this is the error that i get
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: /Default1Controller/MyAction
Can anyone tell me where
I am going wrong. Any help will be highly appreciated. Also I would like to add that I am using VS 2010. .Net 4.0.
Thanks and Regards
Try below code
<input type="button" value="Click Me" onclick="window.location.href('#Url.Action("MyAction","Default1")')" />
You do not need to include 'Controller' as part of the controller name when using Url.Action(), this applies anywhere where you pass in the controller name as a string:
Also, window.location.href is not a function so should be set using =.
This should load to the correct action:
<input type="button" value="Click Me" onclick="window.location.href = '#Url.Action("MyAction","Default1")'" />
window.location.href is a property instead of a method, so you should change the code like this :
onclick="window.location.href = '#Url.Content("~/Default1/MyAction")';"
I'm an MVC newbie so this might sound trivial.I have my 2 Views(EnterLogin.aspx,ShowLogin.aspx) in a folder called LoginForm in Views.
Here is my Global.asax.cs below
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "LoginForm", action = "ShowLogin", id = UrlParameter.Optional } // Parameter defaults
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
}
Here is my ShowLogin.aspx design code
<form method="post" action="EnterLogin" runat="server">
Hello, i'm login page
Enter Name <asp:TextBox ID="txtName" runat="server"></asp:TextBox>
<input type="submit" value="PressMe" />
</form>
Here are my controllers
public class LoginFormController : Controller
{
public ActionResult ShowLogin()
{
return View();
}
public ActionResult EnterLogin()
{
return View("EnterLogin");
}
}
On running the application it first loads with url
http://localhost:50224/
and shows the ShowLogin.aspx View
On clicking the button I'm calling EnterLogin controller to show EnterLogin View but it looks in URL
http://localhost:50224/EnterLogin
instead of
http://localhost:50224/LoginForm/EnterLogin
What could be causing this?
The reason you're not landing where you want to is the action portion of your form:
action="EnterLogin"
This should follow the correct route to ensure it hits the LoginFormController. e.g.
action="/LoginForm/EnterLogin"
Remember that the incoming request needs to match a route specified in RegisterRoutes. Because you don't have anything directly matching EnterLogin it will try to use EnterLogin to fill in the {controller} then default to ShowLogin as the action (resulting in a failed request). basically:
EnterLogin ==resolves==> EnterLogin /ShowLogin/
{controller}/{action} /{id}
Alternatively you can make a named route that will redirect to the correct location if you want to short-hand it:
action="LogMeIn"
and then:
routes.MapRoute(
"Login",
"LogMeIn",
new { controller = "LoginForm", action = "EnterLogin" }
);
Now requesting /LogMeIn will execute LoginForm's EnterLogin() action.
The default route defined in Global.asax defines routes which have /controller/action.
Your controller is called LoginForm and your action is called EnterLogin so this is expected behaviour.
If you want to exclude LoginForm from the URL, you need to define a custom route to allow for this.
routes.MapRoute(
"LoginForm_EnterLogin", // Route name
"LoginForm/EnterLogin/{id}", // URL with parameters
new { controller = "LoginForm", action = "ShowLogin", id = UrlParameter.Optional } // Parameter defaults
);
You may do something like this
Global.asax.cs :-
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "LoginForm", action = "ShowLogin", id = UrlParameter.Optional } // Parameter defaults
);
ShowLogin.aspx :-
<form method="post" action="EnterLogin" runat="server">
Hello, i'm login page
Enter Name <input type="text" name="txtName"/>
<input type="submit" value="PressMe" /> </form>
LoginFormController :-
public class LoginFormController : Controller
{
public ActionResult ShowLogin()
{
return View();
}
[HttpPost]
public ActionResult EnterLogin(FormCollection collection)
{
string Yourtxtname=Collection["txtName"]; //You will get input text value
return View();
}
}