MVC4 - Login box within Layout page using Partial - asp.net-mvc

I have a layout page, and want it to have a Login Box, OR display the logged in user, along with a Logout link.
At the moment, my SiteLayout.cshtml file has this:
<body>
<h1>Basic Finance</h1>
<div>
#if (Request.IsAuthenticated)
{
#Html.ViewBag.UserDisplay
#Html.ActionLink("[Logout]", "LogoutUser", "User")
}
else
{
#Html.Partial("_Login")
}
<hr />
#RenderBody()
</div>
</body>
Then, i my Views/Shared/, I have the _Login.cshtml file:
#model BasicFinanceUI.Models.LoginModel
#using (Html.BeginForm())
{
#Html.ValidationSummary()
<p>
Username: #Html.TextBoxFor(x => x.Username)
Password: #Html.TextBoxFor(x => x.Password)
Remember Me: #Html.DropDownListFor(x => x.RememberMe, new[]
{
new SelectListItem() { Text = "Yes", Value = "true"},
new SelectListItem() {Text = "No", Value = "false"}
}, "Select")
<input type="submit" value="Login" />
</p>
}
This code was moved from a standard view. I had it then there was simply a 'Login' link, instead of the login box in the Layout page. I want to display a login box instead.
My login code is still in a controller I created called 'UserController'. But, I have no idea how to tell my login box to use that controller. Is this the right way to do what I want (or should there be a controller for my login partial). Is it OK to use my 'UserController'? And if so, how?

Change:
#using (Html.BeginForm())
{
#Html.ValidationSummary()
<p>
Username: #Html.TextBoxFor(x => x.Username)
Password: #Html.TextBoxFor(x => x.Password)
Remember Me: #Html.DropDownListFor(x => x.RememberMe, new[]
{
new SelectListItem() { Text = "Yes", Value = "true"},
new SelectListItem() {Text = "No", Value = "false"}
}, "Select")
<input type="submit" value="Login" />
</p>
}
To:
#using (Html.BeginForm("Login", "User"))
{
#Html.ValidationSummary()
<p>
Username: #Html.TextBoxFor(x => x.Username)
Password: #Html.TextBoxFor(x => x.Password)
Remember Me: #Html.DropDownListFor(x => x.RememberMe, new[]
{
new SelectListItem() { Text = "Yes", Value = "true"},
new SelectListItem() {Text = "No", Value = "false"}
}, "Select")
<input type="submit" value="Login" />
</p>
}
Where "User" is your controller and "Login" is your action method that handles the Login's POST.
http://msdn.microsoft.com/en-us/library/dd492590(v=vs.118).aspx

Related

How to validate a duplicate post request from a form in MVC

I am having an form which insert a record whenever a post request is made,but the problem is that if someone clicks submit button more than 1 times than duplicate post request are made and at the end same records are getting inserted. I dont want to check that the record is already present or not because the record would be different always. I tried using ValidateAntiForgeryToken filter in controller but it is failing to validate the requests, Below is my View Code.
#using (Html.BeginForm("Create", "Home",FormMethod.Post,new { onkeydown = "return event.keyCode!=13" }))
{
#Html.AntiForgeryToken()
<div class="right-col">
#Html.TextBoxFor(model => model.Name, new { placeholder = "Name", #class = "small-box" })
</div>
<div class="left-col">Email Id :</div>
<div class="right-col">
#Html.TextBoxFor(model => model.EmailId, new { placeholder = "Email Id", #class = "small-box",id="resumeemailid" })
#Html.ValidationMessageFor(model => model.EmailId)
</div>
<div class="left-col">Address :</div>
<div class="right-col">
#Html.TextAreaFor(model => model.Address, new { placeholder = "Address", #class = "small-box" })
</div>
<div class="buttons resume-threebutton">
<input type="submit" id="register-button" class="gradient-btn" value="#T("Account.Passport.Register.Button.Upload", "Upload")" name="Command" />
<input type="submit" id="register-button" class="gradient-btn" value="#T("Account.Passport.Button.UploadandAdd", "Upload And Add New")" name="Command" />
<input type="button" id="register-button" class="gradient-btn" value="#T("Account.Passport.Register.Button.Cancel", "cancel")" name="register-button" onclick="location.href='#Url.Action("SelectTemplate", "CustomerTemplate")'" />
</div>
}
and below is my controller Post method
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ProductModel model)
{
//To do add the product here...
}

button cannot trigger in mvc 4

I am having some trouble in ASP.NET MVC4 - When I click the Login button it's not hitting my controller and not logging in
This is the code on my .cshtml
#using System.Linq
<body>
<div class="container">
#using (Html.BeginForm("Login", "Login", FormMethod.Post, new { #Class = "form-signin", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "Login failed. Check your login details.")
<img class="img-responsive" src="~/Images/PI%20Logo.jpg" />
#Html.TextBoxFor(m => m.userName, new {#Class = "form-control", #Id = "user", #placeholder = "Username"})
#Html.ValidationMessageFor(m => m.userName)
#Html.PasswordFor(p => p.passwd, new {#Class = "form-control", #Id = "pass", #placeholder = "Password"})
#Html.ValidationMessageFor(m => m.passwd)
<!--<input class="form-control" id="username" placeholder="Username" type="text" />
<input class="form-control" id="Password1" placeholder="Password" type="password" /> -->
<input id="submit" class="btn btn-lg btn-primary btn-block" type="button" value="LOGIN" />
}
</div>
<script src="~/Scripts/jquery-1.11.2.min.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
</body>
and this is my controller
public class LoginController : Controller
{
//
// GET: /Login/
public ActionResult Login()
{
return View();
}
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult Login(Login login)
{
AccountManagement am = new AccountManagement();
var xrm = new XrmServiceContext("Xrm");
SystemUser sysUser = xrm.SystemUserSet.Where(x => x.DomainName == "hc\\" + login.userName && x.IsDisabled == false).FirstOrDefault();
if (am.ValidateCredentials(login.userName, login.passwd) == "True" && sysUser != null)
{
Session["username"] = login.userName;
return RedirectToAction("MainHome", "MainMenu");//Request.CreateResponse(HttpStatusCode.OK, new { Message = "Success", User = sysUser });
}
else
{
ModelState.AddModelError("", "Login data is incorrect!");//Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Username or Password Invalid");
}
return View(login);
}
}
What's wrong with my code - i'm so confused, because many tutorial made simple login like this but it's work
Change button type to submit
<input id="submit" class="btn btn-lg btn-primary btn-block" type="submit" value="LOGIN" />
Difference between input type Button & submit
<input type="button" />
buttons will not submit a form - they don't do anything by default. They're generally used in conjunction with JavaScript as part of an AJAX application.
<input type="submit">
buttons will submit the form they are in when the user clicks on them, unless you specify otherwise with JavaScript.

Partial View models

Within my layout page, I want to either show a Login box, OR the details about the logged in person.
<div>
#if (Request.IsAuthenticated)
{
#Html.ViewBag.UserDisplay
#Html.ActionLink("[Logout]", "LogoutUser", "User")
}
else
{
#Html.Partial("_Login")
}
<hr />
#RenderBody()
</div>
My login partial view:
#model BasicFinanceUI.Models.LoginModel
#using (Html.BeginForm("LoginUser", "User"))
{
#Html.ValidationSummary()
<p>
Username: #Html.TextBoxFor(x => x.Username)
Password: #Html.TextBoxFor(x => x.Password)
Remember Me: #Html.DropDownListFor(x => x.RememberMe, new[]
{
new SelectListItem() { Text = "Yes", Value = "true"},
new SelectListItem() {Text = "No", Value = "false"}
}, "Select")
<input type="submit" value="Login" />
#Html.ActionLink("[Register]", "Register", "User")
</p>
}
When I load the screen, and login, it works fine.
However, when I click 'Register', it loads the register screen. The login box is still visible in the Layout.
My registration screen is displayed:
#model BasicFinanceUI.Models.RegisterationModel
#{
ViewBag.Title = "Register";
Layout = "~/Views/Shared/SiteLayout.cshtml";
}
<h2>Register</h2>
#using (Html.BeginForm("Register", "User"))
{
<p>#Html.ValidationSummary()</p>
<p>Username: #Html.TextBoxFor(x => x.Username)</p>
<p>Password: #Html.PasswordFor(x => x.Password1)</p>
<p>Retype Password: #Html.PasswordFor(x => x.Password2)</p>
<p>Firstname: #Html.TextBoxFor(x => x.Firstname)</p>
<p>Surname: #Html.TextBoxFor(x => x.Surname)</p>
<p>Email: #Html.TextBoxFor(x => x.Email)</p>
<p><input type="submit" value="Register"/></p>
}
When I click the Register button, things go wrong.
I get the error:
The model item passed into the dictionary is of type
'BasicFinanceUI.Models.RegisterationModel', but this dictionary
requires a model item of type 'BasicFinanceUI.Models.LoginModel'.
It seems because there are two forms on the screen, they're getting mixed up. What am I doing wrong?

ActionResult not being called when using [AcceptVerbs(HttpVerbs.Post)]

The ActionResult in the controller is not being called. The page is just refreshing.
Check my code below:
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
#if (#ViewBag.Message != null)
{
<p style="color: #b94a48;">#ViewBag.Message</p>
}
#Html.HiddenFor(model => model.Id)
<div class="form-group">
<label class="control-label visible-ie8 visible-ie9">Username</label>
<div class="input-icon">
<i class="fa fa-user"></i>
#Html.TextBoxFor(model => model.UserName, new { #placeholder = "Email", #class = "form-control placeholder-no-fix" })
<p style="color: #b94a48;">#Html.ValidationMessageFor(model => model.UserName)</p>
</div>
</div>
<div class="form-group">
<label class="control-label visible-ie8 visible-ie9">Password</label>
<div class="input-icon">
<i class="fa fa-lock"></i>
#Html.PasswordFor(model => model.Password, new { #placeholder = "Password", #class = "form-control placeholder-no-fix" })
<p style="color: #b94a48;">#Html.ValidationMessageFor(model => model.Password)</p>
</div>
</div>
<div class="form-actions">
<div>
<label class="checkbox">
#Html.CheckBoxFor(model => model.RememberMe, new { #class = "remember" }) Remember me
</label>
</div>
<button type="submit" class="btn blue pull-right">
Login <i class="m-icon-swapright m-icon-white"></i>
</button>
</div>
</fieldset>
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Login(AccountViewModel model, FormCollection args, string ReturnUrl)
{
}
RouteConfig:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("SJSS", "{controller}/Show/{assetCode}/{action}/{id}", new { controller = "Asset", action = "Index", id = UrlParameter.Optional });
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Account", action = "Home", id = UrlParameter.Optional });
Try altering your #Html.BeginForm to this:
#Html.BeginForm("***Action Name***", "***Controller Name***", FormMethod.Post)
{
}
You need to specify an "Action", "Controller" and "Form method" for your form. See a code below:
#using (Html.BeginForm("Login", "Account", FormMethod.Post))
{
}
I might be mistaken here but despite the fact that your identation is a bit confusing, I can't find the url which you're posting to, I mean, your form action is empty, even if you submit, how would mvc know which action to call?
Try setting the action and controller parameters on Html.BeginForm.
edit: Check #Roman Denysenko's answer to see an example that might suit your case perfectly.

ASP.NET MVC: Multiple submit buttons using Ajax.BeginForm

I want to create a page that has a next button and previous button that switches the image displayed.
For that purpose I created an Ajax.BeginForm and inserted into it, an image and two submit buttons.
Can I (should I) have multiple submit buttons inside an Ajax.BeginForm?
How would the controller handle each submit separately?
Try this,
View
#model TwoModelInSinglePageModel.RegisterModel
#using (Ajax.BeginForm("DYmanicControllerPage", "Test", FormMethod.Post,null, new { id = "frmSignUp" }))
{
<div>
<input type="hidden" id="" name="hidden2" id="hdasd" />
#Html.HiddenFor(m => m.hidden1)
#Html.LabelFor(m => m.Name)
#Html.TextBoxFor(m => m.Name)
#Html.ValidationMessageFor(m => m.Name)
</div>
<br />
<div>
#Html.LabelFor(m => m.Address)
#Html.TextBoxFor(m => m.Address)
#Html.ValidationMessageFor(m => m.Address)
</div>
<br />
<div>
#Html.LabelFor(m => m.PhoneNo)
#Html.TextBoxFor(m => m.PhoneNo)
#Html.ValidationMessageFor(m => m.PhoneNo)
</div>
<input type="submit" value="Save" id="btnSave" name="ButtonType"/>
<input type="submit" value="Next" id="btnNext" name="ButtonType" />
}
Controller
[HttpPost]
public ActionResult DYmanicControllerPage(RegisterModel model, string ButtonType)
{
if(ButtonType == "Next")
{
// Do Next Here
}
if (ButtonType == "Save")
{
//Do save here
}
return JavaScript("REturn anything()");
}
I would recommend that you have two buttons and then depending on what button was clicked you could set the action on the form:
Razor
$(function (){
$("#btn-prev").click(function() {
$("#form").attr
(
"action",
"#Url.Action("Action", "Controller", new {area="Area" })",
).submit();
});
$("#btn-next").click(function() {
$("#form").attr
(
"action",
"#Url.Action("Action", "Controller", new {area="Area" })",
).submit();
});
});
I am using jQuery here to do this, but I think you can get the idea.
I had the same requirement/issue and tried both solutions here and they both work for me. I LIKE the idea of setting the action via jquery when clicking so I can keep my actions separate so they can be used by other views.
HOWEVER, I've found that when I do this while I debug, it posts TWICE and BOTH the OnSuccess and OnFailure are triggered. It only happens when debugging though. Keep this in mind when picking.

Resources