I have started an MVC project and it has created the AccountController Class for me.
So to login to my current site I would have to go to, localhost:2500\Account.mvc\LogOn
I wanted to make the login on my HomeController in the Index view. So basically if you go to my root of the site if not authenticated you would have to login to go anywhere else.
So what I did was add the form to my Index View and tried to have it post to my
Account view calling the LogOn action.
I have called the BeginForm method passing it my action and the respective view (LogOn, Account). When I click the button, it doesn't post to the Account view therefore doesn't execute the LogOn action. Instead, it just posts to the Home view calling the Index action again. So it really does nothing for me... haha.
Not sure what I am doing wrong. Below is my raw form code from Home/Index.aspx and then I also will show you the source after its rendered before hitting the logon button.
Here's my code from Home/Index.aspx:
<% using (Html.BeginForm("LogOn", "Account")) { %>
<div>
<fieldset>
<legend>Account Information</legend>
<p>
<label for="username">Username:</label>
<%= Html.TextBox("username") %>
<%= Html.ValidationMessage("username") %>
</p>
<p>
<label for="password">Password:</label>
<%= Html.Password("password") %>
<%= Html.ValidationMessage("password") %>
</p>
<p>
<%= Html.CheckBox("rememberMe") %> <label class="inline" for="rememberMe">Remember me?</label>
</p>
<p>
<input type="submit" value="Log On" />
</p>
</fieldset>
</div>
<% } %>
View Source of Home.mvc/Index:
<form action="/Account.mvc/LogOn" method="post">
<div>
<fieldset>
<legend>Account Information</legend>
<p>
<label for="username">Username:</label>
<input id="username" name="username" type="text" value="" />
</p>
<p>
<label for="password">Password:</label>
<input id="password" name="password" type="password" />
</p>
<p>
<input id="rememberMe" name="rememberMe" type="checkbox" value="true" /><input name="rememberMe" type="hidden" value="false" /> <label class="inline" for="rememberMe">Remember me?</label>
</p>
<p>
<input type="submit" value="Log On" />
</p>
</fieldset>
</div>
</form>
I set a break point at my LogOn action and it never gets hit, so its not a login error either.
It looks like the action in the html source is set correctly, I just don't understand why it doesn't post correctly. I'm not doing something right. Please let me know if you have any ideas. Thanks!
LogOn Action in the Account View:
[AcceptVerbs(HttpVerbs.Post)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
Justification = "Needs to take same parameter type as Controller.Redirect()")]
public virtual ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl)
{
if (!ValidateLogOn(userName, password))
{
return View();
}
FormsAuth.SignIn(userName, rememberMe);
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
Can you confirm that /Account.mvc/LogOn is a valid route?
Things to check:
Is the route valid?
Does the LogOn action have ActionVerb on it, preventing post requests - such as:
[ActionVerbs(HttpVerbs.Get)]
Edit:
Looking at your code, ignoring the fact that the breakpoint. get redirected to the home page, since you're not passing the returnUrl, won't it just send you back to the home page when it's successful?
Put this in your master page. What does it return?
<%=Request.IsAuthenticated %>
Edit 2:
Apparently this returns false.
Okay... So the controller is okay, and the view looks okay, and is rendering the correct url... I assume that ASP.NET MVC is installed and is in the GAC, given that you can also browse to other urls such as LogOn directly. And it looks like you're running it on Windows XP, given the '.mvc' in the route.
What do your routes look like? Have you made any changes to them?
Related
I am trying to post data from web form to the controller in my asp.net application so that I can authenticate the credentials which the user has enterted.
My code for the web form looks like this at the bottom of this code there is a submit button.
<form action="~/Controller" method="post">
<fieldset>
<legend> Enter your details</legend>
<div>
<label for="name ">name </label>
<input type="text" name="name" value=""/>
When I run the code and then press the submit button I get an error 405 which is because a HTTP method is not allowed. This is code I have in the controller file. Is the error because I have made a mistake in the web forms of its it because of a error in the controller file.
[HttpPost]
public void MyAction(string telephone, string emailadress, string name )
{
}
You can use tag-helpers, like seen below. documentation: https://learn.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-5.0
<form asp-controller="Home" asp-action="MyAction" method="post">
<!-- Input and Submit elements -->
</form>
I have a search box on my site.
The controller looks like this:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SearchResults(SearchModel model)
{
View:
<div class="siteSearch clearfix" role="search">
<form id="HeaderSearchForm">
#Html.AntiForgeryToken()
<label for="tbSiteSearch">Search:</label>
<input type="text" id="tbSiteSearch" name="tbSiteSearch" class="text" />
<button type="submit" class="btn submit">
<i class="icon-search"></i>
</button>
</form>
</div>
So when I do a search, I can see the hidden label with the Anti Forgery Token present. This all works as expected because if I take a blank html page, copy the form code and leave the '__RequestVerificationToken' blank, I get told that the token hasn't been set and the search doesn't run. Which is what I would expect.
The issue I have is if I submit a search, copy the token from my site and place it in to my blank html page e.g.
<html>
<body>
<script>history.pushState('', '', '/')</script>
<form action="https://www.adomainname.co.uk/Search/SearchResults/" method="POST">
<input type="hidden" name="SearchTerm" value="testing" />
<input type="hidden" name="__RequestVerificationToken" value="theverificationtokengoeshere" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
The request is submitted - even if I am running the above code on localhost. I would have expected the form to not submit as it was coming from a different domain. Am I misunderstanding how this should work?
If I refresh the page and resubmit Im obviously allocated a new AFT and so the submit fails again but this doesn't feel right.
Ideally I would prefer the form action to only run on the domain it's on and not be able to execute the action from another site. I thought using AntiForgeryToken prevent Cross-Site Request Forgery.
If any of this is unclear, please let me know and I'll explain more.
I am building a website with WebMatrix. I would like users to enter their name in the main page and after redirection their name will be shown in the results of another form. But my code is not working.
This is a snippet of the main page:
#{
if (IsPost) {
PageData["fullname"] = String.Format("{0} {1}", Request.Form["mainForename"], Request.Form["mainSurname"]);
PageData["redir"] = Request.Form["goTo"];
}
}
<form name="mainForm" id="mainForm" method="post" action="foo.cshtml" onsubmit="return mainValid(this);">
<h2>Please enter your name:</h2>
<label for="mainForename" class="label">Forename:</label>
<input type="text" name="mainForename" id="mainForename">
<label for="mainSurname" class="label">Surname:</label>
<input type="text" name="mainSurname" id="mainSurname">
<input type="submit" name="goTo" value="Go to Form 1">
<input type="submit" name="goTo" value="Go to Form 2">
</form>
This is a snippet of the page that the main page directs to:
#{
if (IsPost) {
var display = PageData["fullname"];
}
}
<form name="form1" id="form1" method="post" onsubmit="return Valid(this);">
<!-- some HTML code -->
<input type="submit" name="submit" value="Get results">
<p>#Html.Raw(display)</p>
</form>
But whatever value I have submitted in the mainForm, PageData["fullname"] and PageData["redir"] seem to have no values. What is the problem?
Any help would be appreciated.
I think PageData is only useful when combining subpages into a single page.
Instead, try the Session object where you are using PageData. Session will be available for all that user's pages.
So where you have PageData["fullname"] use Session["fullname"]
For more details, see http://www.mikesdotnetting.com/article/192/transferring-data-between-asp-net-web-pages
I find something that's not quite good in your code:
Why your form action is set to a cshtml file? It has to be an action in a controler;
Why are you using "hardcoded" form tag? Use #using(#Html.BeginForm('name', 'action', 'controller'...)
Why do you need WebMatrix? 1st - its pretty old, 2nd it for grids - you have a form.
Use a model, and use #Html.TextBoxFor(x=>x.UserName) inside the #Html.BeginForm.
Then post the form in the action you are posting to redirect to another page that contains the 2nd Form, and have a model. The post action should look somehow like this
[HttpPost]
public ActionResult RedirectToAnotherForm(MyModel model)
{
return View('SecondFormView', new SecondFormModel{
userName = model.name
})
}
I'm trying to post some information from a form but it keeps posting null values to the Comment controller rather than what is entered on the page....
#using (Html.BeginForm("SubmitComment", "Comment",FormMethod.Post))
{
<fieldset>
<legend>Submit a comment</legend>
<input id="comment" type="text" />
<button type="submit">Submit</button>
</fieldset>
}
Any ideas?
Add the name="comment" attribute to the input.
I have a simple feedback form on our website. When users enter html in the page, they should get a validation error message. But they don't. The exception is thrown and caught in:
void Application_Error(object sender, EventArgs e)
{
...
}
The exception caught here is:
A potentially dangerous Request.Form value was detected from the
client
at System.Web.HttpRequest.ValidateString(String value, String
collectionKey, RequestValidationSource requestCollection)
Here is the Asp.net MVC markup:
<form action="<%=Url.Action("Create") %>" method="post" class="data-entry-form">
<fieldset class="comment">
Your thoughts:
<div class="editor-field">
<%= Html.TextAreaFor(model => model.Comment, 10, 2, new { placeholder="your message" }) %>
<%= Html.ValidationMessageFor(model => model.Comment) %>
</div>
<br />
E-mail address (optional)
<div class="editor-field">
<%= Html.TextBoxFor(model => model.Email, new { placeholder="you#youremailaddress.com" }) %>
<%= Html.ValidationMessageFor(model => model.Email) %>
</div>
<input type="submit" value="Send" />
</fieldset>
</form>
and here is the generated html:
<form action="/feedback/Create/" method="post" class="data-entry-form">
<fieldset class="comment">
Your thoughts:
<div class="editor-field">
<textarea cols="2" id="Comment" name="Comment" placeholder="your message" rows="10">
</textarea>
</div>
<br />
E-mail address (optional)
<div class="editor-field">
<input id="Email" name="Email" placeholder="you#youremailaddress.com" type="text" value="" />
</div>
<input type="submit" value="Send" />
</fieldset>
</form>
And here is the controller code:
[HttpPost]
public ActionResult Create(Feedback feedback)
{
if (ModelState.IsValid)
{
FillFeedbackObject(feedback);
feedbackRepository.AddFeedback(feedback);
return View("SuccessMessage", new SuccessMessageModel("Thanks for your message!"));
}
return View(feedback);
}
I also have <add key="ClientValidationEnabled" value="true" /> in the appSettings section of the web.config file and I am including jquery.validate.js. So both client side and server side validation fail.
What is wrong?
It's not technically a Model's error, that's why you cannot handle it with Model.IsValid code statement.
If you actually allow html to be submitted in this field or want to sanitize submitted value on server you may annotateComment property of your model with [AllowHtml] attribute. Also, if you want to notify user that they cannot include tags in the text, you may add an error to ModelState during feedback parsing on server side with ModelState.AddModelError() method.
Obviously, leaving request validation in place has it's advantages, and you're correct disabling request validation shouldn't be taken lightly. But there's no graceful way to handle this exception in ASP.NET because it happens so early in the pipeline. It's the actual framework protecting you from yourself.
You can use the Application_Error event that you pointed out in your original post. The come up with some code like:
protected void Application_Error(object sender, EventArgs e)
{
var exception = Server.GetLastError();
if (exception is HttpRequestValidationException)
{
// use Response.Redirect to get the user back to the page, and use session/querystring to display an error
}
}
Try adding the [ValidateInput(false)] attribute to your controller action method.
Source: http://msdn.microsoft.com/en-us/library/system.web.mvc.validateinputattribute.aspx
Edit: If you still want to validate, you should encode the input before sending to the server, for example using HttpUtility.HtmlEncode. The reason the validation blocks the code is because it could be malicious. By encoding it you can allow it to pass through and still have validation enabled. However you may need to change your validation rules/attributes to account for the encoding. In case it wasn't clear before, this option requires validating on the server side once you get to the controller, adding an error to the ModelState as needed, and returning the same view or partial view as needed in case of errors.
With MVC 3 and above you can use the AllowHtml attribute with the property that can contain some html