Why is MVC button link inserting incorrect url - asp.net-mvc

I have a simple mvc login page with a button generating an incorrect link. When I hover over the button, the link, which I believe is the default form action which in turn is the current page, is /resource.ashx?action=login&controller=user. It should be /action=login&controller=user. The url of the page is
http://localhost:57505/User/Login.
Can anyone explain how I would go about determining where / why / how resource.ashx is made part of the form submit action? and more importantly how to fix?
I have considered routing, and javascript files which may be modifying the html but nothing strikes me as a culprit.
The cshtml code is as follows:
#model MyCompany.MyApp.Website.Models.User.LoginViewModel
#{
Layout = "~/Views/Shared/_LoginLayout.cshtml";
ViewBag.Title = "Log in";
}
#using (Html.BeginForm(new { ViewBag.ReturnUrl }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<h1>Welcome to My Website</h1>
<div>
#Html.TextBoxFor(m => m.UserName, new { placeholder = "Username" })
#Html.PasswordFor(m => m.Password, new { placeholder = "Password" })
<button>Login to MyWebsite</button>
<div>
#Html.CheckBoxFor(m => m.RememberMe)
<label for="keep">Keep me logged in for 5 days</label>
</div>
#Html.RouteLink("Password recovery",
routeValues: new { controller = "Password", action = "Forgot" })
<br />
</div>
}
I should also add that this problem occurs on an instance of the solution which I branched in tfs express 2013. there is an extra level in the directory structure than in the original which works although I could not explain why that matters. the problem is the more vexing because the base code works, while the branched code does not. and I copied the working code into the branch to make sure everything was exactly the same, yet the application is adding this additional element, resource.ashx to the computed url. I also set the directory structure the same, but no success.
As a second addition, to answer rowan's question about routing, this is what the application has. I have inherited it, so I may not be able to answer / justify all questions about decisions made.
public class RouteConfig
{
/// <summary>
/// Registers the routes.
/// </summary>
/// <param name="routes">The routes.</param>
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
////routes.LowercaseUrls = true;
// Client website routes
routes.MapRoute(
"user-activation",
"user/activate/{token}",
new { controller = "user", action = "activate" });
routes.MapRoute(
"password-reset",
"password/reset/{token}",
new { controller = "password", action = "reset" });
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
}

I figured out the problem. a third party control, which was not even being used or referenced, but which nonetheless was sitting around in the solution, was the cause of the unexpected route which caused the unwanted url on my login page. deleting the related dlls fixed the problem. however, I do need that component, so will have to work out a solution.
special thanks to rowan for getting me on the right path. all I needed to do was inspect the RouteTable in the debugger, and it became obvious what the cause and culprit were. previously I had relied on eyeballing the code, but it was doing something more than I expected. hence the need to inspect the runtime state - not just design time.

Related

.Net MVC form post failing on server

I created a simple form that works fine when I run it in Visual Studio, but fails on my website with a 404 error.
I have an Action set up to receive only "post" messages using [HttpPost].
If I change the Acton to receive "get" messages, the Action is called, but the form information is not passed along.
This site is written with .Net MVC, could there be some kind of security or something on the server that may need to be changed to allow for "post" calls?
Controller Code -
[HttpGet]
public ActionResult Tester1()
{
return View("Tester1");
}
[HttpPost]
public ActionResult Tester2(MyModel myModel)
{
return View("Tester2", myModel);
}
Tester1.cshtml Code -
#model FS.Models.MyModel
#using (Html.BeginForm("Tester2", "Comics", FormMethod.Post))
{
<div>
Enter Text -
#Html.TextBoxFor(m => m.property1)
</div>
<div>
<input type="submit" value="SEND!" />
</div>
}
Tester2.cshtml Code -
#model FS.Models.MyModel
You entered - #Model.property1
Global.asax.cs Code -
routes.MapRoute(
"Tester2Route", // Route name
"{controller}/Tester2", // URL with parameters
new { controller = "Comics", action = "Tester2" } // Parameter defaults
);
(the code above is just a summarized version, you can visit the actual site here - http://funkysmell.com/Comics/Tester1/)
I was able to get this to work.
The problem is that the server you are running on is wanting a trailing slash (/) after the URL. So when I looked at your example, the URL generated is
<form action="/Comics/Tester2" method="post">
If you add a trailing slash it will work. i.e.
<form action="/Comics/Tester2/" method="post">
Take a look here to get more information.
Why is ASP.NET MVC ignoring my trailing slash?
There are links in that answer to a few blogs which should help you out.

MVC5 Microsoft.CSharp.RuntimeBinder.RuntimeBinderException

Ive been working on converting a MVC4 project over to MVC5. The first day I ran into an 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' but was able to resolve it by starting my conversion over. I'm not sure what the fix was which is a bummer, because its happened again.
The Error occurs in _ExternalLoginsListPartial.cshtml when I load the Login.cshtml page. The error is thrown on line 15. (string action = Model.Action;)
#using Microsoft.Owin.Security
#{
var loginProviders = Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes();
var authenticationDescriptions = loginProviders as AuthenticationDescription[] ?? loginProviders.ToArray();
if (!authenticationDescriptions.Any())
{
<div>
<p>There are no external authentication services configured. See this article
for details on setting up this ASP.NET application to support logging in via external services.</p>
</div>
}
else
{
string action = Model.Action;
string returnUrl = Model.ReturnUrl;
using (Html.BeginForm(action, "Account", new { ReturnUrl = returnUrl }))
{
#Html.AntiForgeryToken()
<div id="socialLoginList">
<p>
#foreach (AuthenticationDescription p in authenticationDescriptions)
{
<button type="submit" class="btn btn-default padded-8 margin-8" id="#p.AuthenticationType" name="provider"
value="#p.AuthenticationType" title="Log in using your #p.Caption account">
<img src="#Url.Content("~/Content/Brands/"+p.Caption+".png")" alt="Microsoft" class="img-responsive" />
<br/>
<b>#p.Caption</b>
</button>
}
</p>
</div>
}
}
}
The error thrown is
An exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll but was not handled in user code
Additional information: 'object' does not contain a definition for 'Action'
The snapshot says
Message : object' does not contain a definition for 'Action'
Source : Anonymously Hosted DynamicMethods Assembly
Now this is double weird because when I set a breakpoint Model.Action is not null. I can see the value.
This is really frustrating. The app was working 5 min ago.. I had changed the html on a non related page.. and now it wont work.
Hackish Fix
I would rather know why this error is happening. That said, I have a quick fix in case anyone else comes across this (Because this is part of part of the default solution). The solution is to not use dynamics. Create your own viewmodel and pass that.
public class ExternalLoginViewModel
{
[Display(Name = "ReturnUrl")]
public string ReturnUrl { get; set; }
[Required]
[Display(Name = "Action")]
public string Action { get; set; }
}
#Html.Partial("_ExternalLoginsListPartial", new ExternalLoginViewModel { Action = "ExternalLogin", ReturnUrl = ViewBag.ReturnUrl })
Check the views in the Account folder and for each one that has an explicit model, make sure the (view)model is in the right namespace. Mouse over the m parameter (m => m.UserName ... etc) and make sure it is referencing the correct (view)model.
In my case, I moved AccountViewModels to a different folder and the app broke as above. It appears the views are sort of "caching" the model from the original namespace. I used a silly fix (commented out the #model line and un-commented it back). Got warning that m is dynamic but when built and ran it worked. Looks like a glitch in VS 2013 RTM.
This bug is verified by Microsoft, and they are working on fixing it.
So anyone from the future who reads this: try updating visual studio 2013 to at least update 2.
https://connect.microsoft.com/VisualStudio/feedback/details/813133/bug-in-mvc-5-framework-asp-net-identity-modules
Found a solution for my own (mvc5) project after some experimenting.
I had a _ExternalLoginsListShoppingCartPartial.cshtml (from my mvc4 project) with #model ICollection<AuthenticationClientData> at the top. I commented it out and rebuild the solution and suddenly it works. I'm not even using that partial view in any view so it's a pretty nasty bug imo.
So check in your project. You may have some mvc4/simplemembership stuff that is messing up your mvc5 project.
I got the same error after replacing account models to another folder. When I double checked each view under the Account folder I found out my "Manage.cshtml" referenced to old namespace. I changed it to correct namespace for my models and the error fixed.
For me I had changed the contents of the ManageUserViewModel to add a property... I then started getting the error. When I changed the Manage.cshtml from not using an explicit model to using:
#model XYZ.Models.ManageUserViewModel
and removed the using statements, it started working again. One hour wasted!
I also hit this issue with VS 2013 U3. I had just added an email field to RegisterViewModel with the [EmailAddress] attribute, and it was crashing when I tried visiting the Register page. Commenting out the [EmailAddress] attribute fixed the issue. However, it continued working after I added the attribute back in, so this is probably a broader issue that could have to do with changes to the model classes.
yeah, I replaced the "else" code with the following and its working but still trying to see why it didn't work when using Model.Action ?
//string action = Model.Action;
//string returnUrl = Model.ReturnUrl;
//using (Html.BeginForm(action, "Account", new { ReturnUrl = returnUrl }))
using (Html.BeginForm("ExternalLogin", "Account", new { ReturnUrl = ViewBag.ReturnUrl }))

MVC application throws an error "Resource cannot be found"

I am new to MVC. I created an empty mvc application. Later added a view, a controller and a model for the view. After adding these three parts into the application, i tried running the application. But, i got "resource cannot be found" error from the browser. I cannot figure out the reason behind this.
Is there any settings to be modified to make it run properly? I did not change any settings.
Can anyone help me out of this?
Thanks
Manikandan
Add class config the default route and call it from global.asax
And of course add Home controller with action Index
public static class RouteConfig
{
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 }
);
}
}
If all you've done is as you described, then the most likely cause for this is that you've used a Visual Studio template that doesn't include some scripts that are referenced in the auto-generated views you created.
Try opening the view that has this error (the view that you added) and remove its Scripts.Render directives, then run your app again and see if it goes away.
If it does go away using the above, then the problem is these missing scripts. In that case, you may either choose not to have them in your app or install them using nuget.
You probably didn't request the correct url in your browser or you didn't name your controller correctly.
Let's suppose that you wanted to add a HomeController.
Here are the steps:
Create a new ASP.NET MVC Empty Application
Add ~/Controllers/HomeController.cs
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
Add ~/Views/Home/Index.cshtml:
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
</head>
<body>
<div>
</div>
</body>
</html>
Run the application and navigate to /Home/Index

Can .net mvc routing cause JavaScript errors?

I am having a lot of trouble using routing infrastructure of asp.net mvc2. I have following routes registered in my global.asax file
routes.MapRoute(
"strict",
"{controller}.mvc/{docid}/{action}/{id}",
new { action = "Index", id = "", docid = "" },
new { docid = #"\d+"}
);
routes.MapRoute(
"default",
"{controller}.mvc/{action}/{id}",
new { action = "Index", id = "" },
new { docConstraint = new DocumentConstraint() }
);
The problem is with first route ("strict"). Three kind of urls can match first route. mycontroller/23/myaction, mycontroller/23/myaction/12 or mycontroller/23/mvaction/stringid. If I try to use this route without specifying value of id everything works fine for example:
Html.ActionLink("Link text", "ActionName", new{docid = 23});
Everything goes well, but if I use links like:
Html.ActionLink("Link text", "ActionName", new{docid = 23, id = 223})
This will produce url currentcontroller.mvc/23/ActionName/223 that is absolutely correct but when it loads the page it gives a JavaScript error in jquery1.4.2.min.js file.
This is strange: if I change id to someid =223 it will reflect in query string and there will be no JS error.
Edit: I have done some further debugging and found when both id and docid are mentioned in route values one thing is ignored in global.asax that is the ignore path.
routes.RouteExistingFiles = false;
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.ignoreRoute is totally bypassed and I can see names of JS files in route value dictionary while debugging in my controller.
it gives javascript error in
jquery1.4.2.min.js file
The most likely cause for this is that something you are displaying on the page is different and you are performing an action that is causing the error. Can you supply enough of a sample from the rendered page to show what you are using jQuery for?
If we drag scripts from solution explorer to site.master it results in following output
<script type="text/javscript" src="../../scripts/jquery.min.js"></script>
The leading dots (..) are creating the problem. Putting source path in url.content or using /scripts instead of ../../scripts will solve the problem because these leading periods are forcing them to match some route in global.asax.

Asp.Net MVC Url.RouteUrl Problem on Windows 2003 vs. Visual Studio 2008

I'm seeing a difference in the output from Url.RouteUrl between my development machine and my deployment server. I'm running Visual Studio 2008 and my deployment box is Windows 2003 Server. I have configured the Global.asax.cs to run with the .aspx extension in my routing tables. However, when I use the "Search-Basic" named route, there is no output from Url.RouteUrl("Search-Basic", new {category = "Test", searchExpression = "search this"})
View Code:
<%= Url.RouteUrl("Search-Basic", new {category = "test", searchExpression="search this"}) %>
Global.asax.cs Code:
// routes for IIS 6 and version below
routes.MapRoute(
"Search-Basic",
"Search.aspx/Basic/{category}",
new { controller = "Search", action = "Basic", category = "All" }
);
routes.MapRoute(
"Default", // Route name
"{controller}.aspx/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
routes.MapRoute(
"Root",
"",
new { controller = "Home", action = "Index", id = "" }
);
On my development box, I get the expected output: /Search.aspx/Basic/Test?searchExpression=search%20this
However, on my deployment server I get no output at all. One difference perhaps is that I'm running the application in a virtual directory on my deployment server; something like: http://testmachine.com/sm/testappname/ where "/sm" is a virtual directory and "/testappname" is a virtual directory holding my application.
Any ideas?
Thank you kindly.
Are you running the same version of ASP.NET MVC because there is a bug in the RC1 (non-refresh) that causes this behavious when you have a route where e.g. the controller is not specified in the route:
The other regression is that in some
cases, the RouteUrl (and thus
RouteLink) methods return an empty
string when you specify a route name,
but the route has default parameters
which are not parameters in the URL.
For example, if you have the following
route:
routes.MapRoute("route-name", "foo/bar", new {controller="Home", action="index"});
Notice that controller has default
value, but is not part of the URL. If
you then specify:
<%= Url.RouteUrl("route-name") %>
You might expect that it would use
that route to render the URL, but it
doesn’t. This bug was introduced when
we refactored all our url generating
helpers to call into a common method.
It turns out, however, that our
RouteUrl methods (aka non-MVC
specific) should have subtly different
behavior than the MVC specific methods
(such as Action). We added a flag to
the common method so that this
difference is taken into
consideration. This was a fix that did
not have a large surface area.
See http://haacked.com/archive/2009/01/30/aspnetmvc-refresh.aspx

Resources