im new in asp.net mvc. i watch a tutorial and he is using webmatrix. i tried to add column named "IDViewer" in table "UserProfile" in my database created by webmatrix. but then, when i tried to insert some value it returns me an error of "Invalid column name 'Length'." but i did not declare column name "Length" in my code. please check my codes and the images. thank you
Images Link Here. please take a look
The error
My database, i added column named IDViewer
public class Register
{
[Required(ErrorMessage = "Please provide password", AllowEmptyStrings = false)]
public string Username { get; set; }
[Required(ErrorMessage = "Please provide password", AllowEmptyStrings = false)]
[DataType(System.ComponentModel.DataAnnotations.DataType.Password)]
[StringLength(50, MinimumLength = 8, ErrorMessage = "Password must be 8 char long.")]
public string Password { get; set; }
public string IDViewer { get; set; }
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary("", new { #style = "color: red" })
<label>Username</label>
#Html.TextBoxFor(m => m.Username, new { #class = "form-control" })
<label>Password</label>
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
<label>Student ID</label>
#Html.TextBoxFor(m => m.IDViewer, new { #class = "form-control" })
#Html.DropDownList("role",roles,"Select Account Type")
<button class="btn btn-primary">Register</button>
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Register(Register registerdata, string role)
{
if(ModelState.IsValid)
{
try
{
WebSecurity.CreateUserAndAccount(registerdata.Username, registerdata.Password, registerdata.IDViewer);
Roles.AddUserToRole(registerdata.Username,role);
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException)
{
ModelState.AddModelError("", "Sorry the username already exists");
return View(registerdata);
}
}
ModelState.AddModelError("","Data invalid");
return View(registerdata);
}
From the documentation, the 3rd parameter is a dictionary
propertyValues
Type: System.Object
(Optional) A dictionary that contains additional user attributes. The default is null.
so your method needs to be
WebSecurity.CreateUserAndAccount(registerdata.Username,
registerdata.Password, new { IDViewer = registerdata.IDViewer });
Related
I am just a beginner of ASP.NET MVC. I just started with creating my login page it works fine but I have a problem when the user inputs wrong credentials. This is what I have done:
UserProfile
public partial class UserProfile
{
public int UserId { get; set; }
[Display(Name = "User name")]
[Required(ErrorMessage = "Username is required.")]
public string UserName { get; set; }
[Display(Name = "Password")]
[DataType(DataType.Password)]
[Required(ErrorMessage = "Password is required.")]
public string Password { get; set; }
public bool IsActive { get; set; }
}
HomeController:
public class HomeController : Controller
{
public ActionResult Login()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(UserProfile objUser)
{
if (ModelState.IsValid)
{
using (DB_Entities db = new DB_Entities())
{
var obj = db.UserProfiles.Where(a => a.UserName.Equals(objUser.UserName) && a.Password.Equals(objUser.Password)).FirstOrDefault();
if (obj != null)
{
Session["UserID"] = obj.UserId.ToString();
Session["UserName"] = obj.UserName.ToString();
return RedirectToAction("UserDashBoard");
}
}
}
else
{
ModelState.AddModelError("", "Invalid Credentials");
}
return View(objUser);
}
public ActionResult UserDashBoard()
{
if (Session["UserID"] != null)
{
return View();
}
else
{
return RedirectToAction("Login");
}
}
}
And the View
#model MyWebApplication.Models.UserProfile
#{
ViewBag.Title = "Login";
}
#using (Html.BeginForm("Login", "Home", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.UserName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.UserName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.UserName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Password, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Password, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Login" class="btn btn-default" />
</div>
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
I am not sure why the message "Invalid Credentials" is not being displayed when the user types a username that isn't stored in the database.
In your question you don't state whether or not in your if statement if the line ModelState.AddModelError("", "Invalid Credentials"); is being hit, which I doubt it is.
Your if statement is constructed wrong, because as of now you're only wanting to display the Invalid Credentials error if the ModelState is not valid.. not whether or not the user's credentials exist.
So you need to rewrite your if statement to this:
if (ModelState.IsValid)
{
using (DB_Entities db = new DB_Entities())
{
var obj = db.UserProfiles.Where(a => a.UserName.Equals(objUser.UserName) && a.Password.Equals(objUser.Password)).FirstOrDefault();
if (obj != null)
{
Session["UserID"] = obj.UserId.ToString();
Session["UserName"] = obj.UserName.ToString();
return RedirectToAction("UserDashBoard");
}
else
{
ModelState.AddModelError("", "Invalid Credentials");
}
}
}
Not to be picky, but hopefully your UserName property is unique, because if you have 2 users that have the same exact UserName and Password and you get the FirstOrDefault occurrence, then you could possibly be letting a user sign in with another's credentials. So I would ensure that the UserName property is unique and change FirstOrDefault to SingleOrDefault.
But if it does, then here is what needs to change:
Option 1
If you want the error message to be displayed under the textbox then in your controller change this:
ModelState.AddModelError("", "Invalid Credentials");
To:
ModelState.AddModelError("UserName", "Invalid Credentials");
AddModelError takes 2 parameters.. the key and the errorMessage for that key. The key is the property name in your model.
public void AddModelError(
string key,
string errorMessage
)
Option 2
If you do not want to display the error message under the textbox, but rather at the top of the form:
Then change this:
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
To:
#Html.ValidationSummary(false, "", new { #class = "text-danger" })
For option 2, you need to read the overloaded methods carefully. Per MSDN in correlation with how you have your ValidationSummary setup.. the first parameter is bool excludePropertyErrors.. you had that set to true so you were excluding Property errors, which is why I proposed to change that to false, so Property errors would be included.
public static MvcHtmlString ValidationSummary(
this HtmlHelper htmlHelper,
bool excludePropertyErrors,
string message,
IDictionary<string, object> htmlAttributes
)
Let me know if this helps.
This question already has an answer here:
MVC model validation
(1 answer)
Closed 6 years ago.
I have a form like following in my MVC application:
#using (Html.BeginForm("Register", "User", FormMethod.Post))
{
<div>
#Html.TextBoxFor(m => m.FirstName, new { placeholder = "First name", #class = "form-control", #type = "text" })
</div>
<div>
#Html.TextBoxFor(m => m.LastName, new { placeholder = "Last name", #class = "form-control", #type = "text" })
</div>
<div>
#Html.TextBoxFor(m => m.Email, new { placeholder = "Email", #class = "form-control", #type = "email" })
</div>
<div>
#Html.TextBoxFor(m => m.Password, new { placeholder = "Password", #class = "form-control", #type = "password" })
</div>
<div>
#Html.TextBoxFor(m => m.PasswordConfirm, new { placeholder = "Confirm password", #class = "form-control", #type = "password" })
</div>
<div>
#Html.DropDownListFor(model => model.SelectedCountryId, Model.Countries, new { #class="select2_single form-control select2-hidden-accessible", #tabindex = "-1" })
</div>
<div>
<input class="btn btn-default submit" type="submit" value="Register" />
</div>
}
My ViewModel looks like following:
public class UserRegistrationViewModel
{
[Required(ErrorMessage = "First name is required!")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last name is required!")]
public string LastName { get; set; }
[Required(ErrorMessage = "Email name is required!")]
public string Email { get; set; }
[Required(ErrorMessage = "Password name is required!")]
public string Password { get; set; }
[Required(ErrorMessage = "Password confirmation name is required!")]
public string PasswordConfirm { get; set; }
public int SelectedCountryId { get; set; }
[Required(ErrorMessage = "Country needs to be selected!")]
public SelectList Countries { get; set; }
}
And these are my two actions:
public ActionResult Index()
{
var model = new UserRegistrationViewModel();
var countries = Connection.ctx.Countries.OrderBy(x => x.CountryName).ToList();
model.Countries = new SelectList(countries, "CountryId", "CountryName");
return View(model);
}
[HttpPost]
public ActionResult Register(UserRegistrationViewModel model)
{
if (ModelState.IsValid)
{
var user = new Users();
user.FirstName = model.FirstName;
user.LastName =model.LastName;
user.Email = model.Email;
user.PasswordSalt = Helpers.PasswordHelper.CreateSalt(40);
user.PasswordHash = Helpers.PasswordHelper.CreatePasswordHash(model.Password, user.PasswordSalt);
user.CountryId = Convert.ToInt32(model.SelectedCountryId);
user.Active = true;
Connection.ctx.Users.Add(user);
Connection.ctx.SaveChanges();
var role = new UserRoles();
role.RoleId = 2;
role.UserId = user.UserId;
role.Active = true;
user.UserRoles.Add(role);
Connection.ctx.SaveChanges();
return RedirectToAction("Index");
}
return null;
}
Now my question here is what do I do if the model state is not valid (ie. display the error messages that I've set up in my ViewModel)???
Do I just do `return View(); or ??
I need to render those messages on my view now...
Whenever I get an invalid form being submitted, I return the View() back for them to correct the issue. Taking them to an error page where they would have to come back to the form and start again would frustrate the user. Give them back the invalid form and tell them what needs correcting.
Now, what needs correcting can be read from the ViewBag(). Or you can have inside you Model some properties that will hold your error message for the user and display them if they are not null.
In the case of an invalid model state, you can just return the current view with the model as a parameter:
if (!ModelState.IsValid)
{
return View(model);
}
EDIT: In your html, add the html elements to show the validation messages:
#Html.ValidationMessageFor(model => model.FirstName)
I'm very new to MVC 5 and web programming in general so please bear with me.
I have a view (used to manage user roles) where I have three separate forms, which I more or less copied and pasted from a tutorial. In the tutorial the fields for the forms were created in the following way:
Username : #Html.TextBox("Username")
Since I wanted the styling to work for them, I changed the code to look more like the default forms in the MVC 5 template, so it ended up looking like this:
#Html.LabelFor(m => m.GetRolesUsername, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.GetRolesUsername, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.GetRolesUsername, "", new { #class = "text-danger" })
</div>
My model ManageUserRolesViewModel looks like this (note that at the top of my view I have #model ManageUserRolesViewModel):
public class ManageUserRolesViewModel
{
#region Assign Role
[Required]
[Display(Name = "Username", ResourceType = typeof(Resources))]
public string AssignRoleUsername { get; set; }
[Required]
[Display(Name = "RoleName", ResourceType = typeof(Resources))]
public string AssignRoleRole { get; set; }
#endregion
#region Get Roles
[Required]
[Display(Name = "Username", ResourceType = typeof(Resources))]
public string GetRolesUsername { get; set; }
#endregion
#region Unassign Role
[Required]
[Display(Name = "Username", ResourceType = typeof(Resources))]
public string UnassignRoleUsername { get; set; }
[Required]
[Display(Name = "RoleName", ResourceType = typeof(Resources))]
public string UnassignRoleRole { get; set; }
#endregion
}
Notice how I'm using annotations to load the name of the elements in the ViewModel directly from resources. I'm doing this for localization purposes, and the resources are returning strings in Spanish. I think this may be the root of my issue, but I'm not sure.
Then, in my controller I have the following method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult GetRoles(string UserName)
{
if (!string.IsNullOrWhiteSpace(UserName))
{
ApplicationUser user = context.Users.Where(u => u.UserName.Equals(UserName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
ViewBag.RolesForThisUser = this.UserManager.GetRoles(user.Id);
ViewBag.Roles = context.Roles.OrderBy(r => r.Name).ToList().Select(rr => new SelectListItem { Value = rr.Name.ToString(), Text = rr.Name }).ToList();
}
return View("ManageUserRoles");
}
Now, here's what happens: if I use Username : #Html.TextBox("Username"), when the method GetRoles() gets called in the controler, the UserName parameter is there and the user is successfully loaded. If instead I use the
#Html.LabelFor(m => m.GetRolesUsername, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.GetRolesUsername, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.GetRolesUsername, "", new { #class = "text-danger" })
</div>
when the method gets called, the UserName parameter is null.
My wild guess is that somewhere in the code MVC is looking for UserName or Username and finding Usuario instead, but I am not sure if this is true and in any case, I'd like to know how to solve the issue.
Assuming your form has the model defined as:
#model ManageUserRolesViewModel
and somewhere in the view:
#Html.TextBoxFor(m => m.GetRolesUsername, new { #class = "form-control" })
The action should look like this:
[HttpPost]
public ActionResult GetRoles(ManageUserRolesViewModel vm)
{
string userName = vm.GetRolesUsername;
//rest of code omitted.
}
So you do not rely on the UserName parameter and can use the view model itself.
if this does not suffice, you could do this:
#Html.TextBoxFor(x => x.GetRolesUsername, new { Name = "UserName" })
Hi Eric,
#Html.TextBox("Username")
// It creates a html input element with name "Username"
<input type="text" id=""Username" name="Username" value="" />
And
#Html.TextBoxFor(m => m.GetRolesUsername)
// It also create a html element with name as it's property name. ie, "GetRolesUsername"
<input type="text" id=""Username" name="Username" value="#Model.GetRolesUsername" />
So, if you submit your form, your browser will send parameters as,
Username = "value in the #html.TeaxtBox()",
GetRolesUsername = "value in the #html.TextBoxFor()"
So, both values will be passed to your MVC controller. Then you can decide what parameters you want to receive.
public ActionResult Submit(string Username, string GetRolesUsername)
{
// You can get Username and GetRolesUsername here
}
public ActionResult Submit(string Username)
{
// You tell your controller that I am expecting only one parameter and that is Username
}
Then there will be a main difference between `#html.TextBox()` and `#html.TextBoxFor()' is,
`#html.TextBox()` will just create a text element. But, `#html.TextBoxFor()' will create and set value to the element.
Hope this will help you.
If you have any doubts, please feel free to ask me.
**And Grand Welcome To MVC.**
I am also just a beginner in MVC :)
I have form which validate inputed email on uniqueness.
<form id="emailValidationForm">
#Html.ValidationSummary(true, String.Empty, new {#class = "text-danger text-center"})
<div class="form-group text-center">
<div class="input-group margin-bottom-5 margin-top-10">
<span class="input-group-addon"><i class="fa fa-user"></i></span>
#Html.TextBoxFor(m => m.Email, new {#class="form-control", #placeholder="Enter your Email",#data_toggle="tooltip"})
#*<input type="text" name="Email" placeholder="Enter your Email" class="form-control" data-toggle="tooltip">*#
</div>
#Html.ValidationMessageFor(m => m.Email, null, new { #class = "text-danger text-center" })
</div>
<div class="text-right">
<button type="submit" class="btn-u btn-u-wide btn-u-orange" title="Validate email">Join</button>
</div>
</form>
Email is part of next Model :
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
So, when i type nothing in text-box i will get error. When i type email that is already registered, i will get also error from function which checks uniqueness.
[AllowAnonymous]
public JsonResult EmailValidation(string email)
{
if (ModelState.IsValid)
{
var user = _service.FindByEmail(email);
if (user == null)
{
return Json(new {result = true, message = "Email is validated"}, JsonRequestBehavior.AllowGet);
}
ModelState.AddModelError(string.Empty, "Email already exists");
return Json(new
{
result = false,
message =
RenderRazorViewToString("~/Views/Account/_RegisterPartialView.cshtml",
new RegisterViewModel {Email = email})
}, JsonRequestBehavior.AllowGet);
}
return Json(new {result = false, message = "Input Email"}, JsonRequestBehavior.AllowGet);
}
But then client validation doesn't works, i can input nothing in email text-box and it will go on.
How can i fix it?
I use jquery 1.10.2 and jquery.validate for validation. Work on MVC5. Use Bootstrap3 for styling.
Also i have set custom defaults:
$.validator.setDefaults({
highlight: function (element) {
$(element).closest(".input-group").addClass("has-error");
},
unhighlight: function (element) {
$(element).closest(".input-group").removeClass("has-error");
}
});
That script is in partialView (i try to replace it in js-module that is used on partialView, but this doesn't works. So i left script it in partialView)
You need to add the remote annotation to the Email-field:
[Remote("EmailValidation","<ControllerName>", ErrorMessage="{0} already has an account, please enter a different email address.")]
public string Email { get; set; }
Also it appears to me like you are mixing two concepts here. The validation-check should be a simple JSON-result like this:
public JsonResult EmailValidation(string email)
{
var user = _service.FindByEmail(email);
return user == null
? Json(true, JsonRequestBehavior.AllowGet)
: Json(false, JsonRequestBehavior.AllowGet);
}
I am using the ASP.NET web application template and trying to allow a user to pick a role when registering.
Here is what I got at the moment.
Does it
View
<fieldset class="col-lg-5 .col-md-5">
<legend>Registration Form</legend>
<p>
#Html.LabelFor(m => m.UserName)
#Html.TextBoxFor(m => m.UserName, new { #class = "form-control" })
</p>
<p>
#Html.LabelFor(m => m.Password)
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
</p>
<p>
#Html.LabelFor(m => m.ConfirmPassword)
#Html.PasswordFor(m => m.ConfirmPassword, new { #class = "form-control" })
</p>
<p>
#Html.DropDownListFor(model => model.Type, Model.TypeList)
</p>
<input type="submit" value="Register" class="btn btn-default" />
</fieldset>
Model
public class RegisterModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
public string Type { get; set; }
public IEnumerable<SelectListItem> TypeList
{
get
{
return new List<SelectListItem>
{
new SelectListItem { Text = "athlete", Value = "athlete"},
new SelectListItem { Text = "coach", Value = "coach"},
};
}
}
}
Controller
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
Roles.AddUserToRole(model.UserName, model.Type);
WebSecurity.Login(model.UserName, model.Password);
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
I am feel like I am close but I can't quiet get it and i am getting this error
Compiler Error Message: Models.RegisterModel>' does not contain a definition for 'DropDownListFor' and the best extension method overload 'System.Web.Mvc.Html.SelectExtensions.DropDownListFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>, System.Collections.Generic.IEnumerable)' has some invalid arguments
Did you initialize your model in HttpGet Register method? Like below...
[AllowAnonymous]
public ActionResult Register()
{
var model = new RegisterModel();
return View(model);
}
I create an empty template MVC4 app, added your code, got object reference not set error as default Register model does not pass model object to view which you are trying to access (i.e. loading TypeInt in DropDownListFor()).
I then initialized model in Get method as shown above. All works fine, i was able to pick a role on register view.
Check if this helps.
take a look your last comma should be removed:
new SelectListItem { Text = "athlete", Value = "athlete"},
new SelectListItem { Text = "coach", Value = "coach"}