I am having a problem using the remote property of the data-anotation.
I am having a model for user which stores the data:
[DataType(DataType.EmailAddress,ErrorMessage="please enter valid email")]
[DisplayName("Email Address")]
[Required(ErrorMessage = "Email is Required")]
[Remote("CheckUniqueEmail","User",ErrorMessage="An account with this email address already exists.")]
public string Email { get; set; }
and I am checking the distinct user email while creating the new one...
When I try to login with the email and password in the different controller, it still calls the Remote and checks for the unique email...
I think I have to exclude the email and password property in the Login controller - but I don't know how.
you need to use 2 different view models, one for creating an account and one for logging in.
You should use another model for logging in at LoginController.
These validations will be used everywhere you use this model.
You can also use the MetadataType to reuse the same base model and apply different validations. Example Here.
Related
I have a model for login logic. It contains a property called Password:
[Required(ErrorMessage = " ")]
[DataType(DataType.Password)]
public string Password { get; set; }
When Veracode scans the model it produces the following error:
CWE-316: Cleartext Storage of Sensitive Information in Memory
My view is generating the Password field as follows:
#Html.EditorFor(x => x.Password}
Then, along the line in the model, I'm using the following Windows Authentication logic to check if the user is a windows user:
DirectoryEntry de = new DirectoryEntry("LDAP://" + System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName, username, password, AuthenticationTypes.Secure);
The above class' constructor requires password as a string.
What would be the best solution that could fix the Veracode problem and allows me to use the logic I already have?
The solution was an easy one. I just have to change the declaration Password to UserIdnt.
Now Veracode doesn't recognize it as a security threat and let it go
I am currently using Asp MVC / Identity 2.0 to build a membership site.
I have made some changes that now allow a user todo the following :
Create separate username / email values on account creation
Login using either username or email through a single text field
What I am concerned about is should user Alice register an account as follows :
Username - Alice
Email - alice#example.com
User Bob could create an account as follows :
Username - alice#example.com
Email - evilbob#l33th4x0rs.com
I'd like to ensure, that should a user create an account, their username is unique in both the UserName and EmailAddress columns.
I have currently achieved within my RegisterViewModel as follows
[RegularExpression(#"^([a-zA-Z0-9 \.\&\'\-]+)$", ErrorMessage = "{0} must be alpha numeric")]
[Display(Name = "Username")]
public string UserName { get; set; }
As such it is not possible to enter an email into the username field - is this the best way to do this though?
I'm concerned that later down the line, I may want to allow some special characters in the username field.
Forgive me if this is a n00b question, I'm still very much new to this.
You cannot ensure uniqueness of your records using the Data annotations you have in your view model properties. Those are for helping validations & display purposes primarily.
What you should be doing is checking the userName value againist both UserName and Email field of your User table and allow/deny user to continue his action.
To check the userName against both email and userName fields , you might try something like this.
var userNameToCheck="alice#ss.com";
var exists=db.Users.Any(x=>x.UserName==userNameToCheck||x.Email==userNameToCheck);
if(!exists)
{
// New record. Let's continue saving it.
}
But a better solution is to use email as your username for the app(Only one column in db table) and keep a unique constraint on that column(Email) to prevent accidental duplicate entry even if your code failed to stop the duplicate entry insertion.
You should always have validation in your code and db (constraints) to be on the safer side.
I am using MVC3 and in certain locations in the code I am using the System.ComponentModel.DataAnnotations.DataType.EmailAddress attribute and letting MVCs Model validation do the validation for me.
However, I would now like to validate an email address in a different section of code where I am not using a model. I would like to use the same method that is already being used by MVC, however I was unable to find any information on how to do so.
EDIT - Sorry if my question was unclear. I will attempt to clarify.
Here is a snippet from the RegisterModel that is included with the default MVC template:
public class RegisterModel
{
...
[Required]
[DataType(DataType.EmailAddress)]
[DisplayName("Email address")]
public string Email { get; set; }
...
}
These attributes instruct mvcs model validation on how to validate this model.
However, I have a string that should contain an email address. I would like to validate the email address the same way that mvc is doing it.
string email = "noone#nowhere.com";
bool isValid = SomeMethodForValidatingTheEmailAddressTheSameWayMVCDoes(email);
As others have said, the DataType attribute doesn't actually do any validation. I would recommend you to look at Data Annotations Extensions which includes already written validation extensions for a variety of things, including Email.
It is also possible to do model validation on your full model explicitly: Manual Validation with Data Annotations.
If you want to do per attribute validation for a specific field/property, you can also look at the tests for DataAnnotationExtensions which should give you what you want:
[TestMethod]
public void IsValidTests()
{
var attribute = new EmailAttribute();
Assert.IsTrue(attribute.IsValid(null)); // Don't check for required
Assert.IsTrue(attribute.IsValid("foo#bar.com"));
..
}
Have a look at this blog post by Scott Guthrie, which shows how to implement validation of an email address using a custom attribute (based on the RegularExpressionAttribute).
You can reuse that logic if you need to validate the email address somewhere else.
You may want to look at this question: Is the DataTypeAttribute validation working in MVC2?
To summarize, [DataType(DataType.EmailAddress)] doesn't actually validate anything, it just says "hey, this property is supposed to be an e-mail address". Methods like Html.DisplayFor() will check for this and render it as foo, but the IsValid() method is pretty much a simple return true;.
You'll have to roll your own code to actually perform validation. The question linked above has some sample code you can use as a starting point.
I have a class User, that have an Email property, like that :
public class User : Entity
{
...
[Display(Name = "Email"), Required(ErrorMessage = "Required."), Remote("EmailExists", "User", ErrorMessage = "Email already in Use.")]
public virtual string Email { get; set; }
...
}
My View Create works fine with all the validation ...
But in my view Edit, my Email texbox is Readonly, so The user cant change the email...
The problem is my Remote validation EmailExists keeps firing...
Is there a way to exclude the Email client validation just in that case? Or maybe another solution?
Thanks
Best solution would be to render Email as text content(span, p, etc) in that particular case - validations would not fire. This would be best accomplished with editor templates. But if you don't wish to, you could use some javascript to remove rules on client side. Take a look at Plugins/Validation/rules - you would remove rule when textbox is readonly. But for me the first way is preferred option
I think that the easier way is to disable the field in the client instead of using readonly. The validate plugin doesn't take in account disabled fields.
You could use different ViewModels for the edit and create views and only apply the Remote attribute to view model associated with the create view or call some other remote validation logic for the view model associated with the edit view.
I’ve got an unexpected situation when using Remote Attribute in ASP.NET MVC3.
The model type I used:
using System;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;
namespace dTweets.Models
{
// at first time, user should create his account with unique username
// as in twitter.com, user do
public class UserMetadata
{
[HiddenInput]
internal int Identity { get; set; }
[Remote("IsUserExist", "Account")] // at any HttpPost, username should
// be unique – not appropriate if
// updating/editing this model later
[Required(ErrorMessage = "username should be unique")]
public string UserName { get; set; } // user cannot change it, later
[DataType(DataType.Password)]
public string Password { get; set; } // user can also change password, later
[DataType(DataType.MultilineText)]
public string About { get; set; } // Optional field – user can edit it later
}
[MetadataType(typeof(UserMetadata))]
[Bind(Include="UserName, Password, About")]
public partial class User
{
}
}
Remote attribute validates user unique name at account creation time. But when later user wants to update/change his account, Remote attribute did not allow to update model if keeping user unique name the same one.
This is not appropriate result because rarely user changes their unique user name. They just change other fields like About field or password etc.
[Note: at account creation time, I want to check user unique name so I used Remote attribute here, but at later time when updating user account I no longer need Remote attribute]
I must remove Remote attribute for updating this model later.
I want to update/change this model without changing user unique name (remote attribute is applied to this unique name).
one way to do this is to send ID value of this record in AdditionalFields named parameter like
[Remote("IsUserExist", "Account",AdditionalFields = "Identity")]
and then you can check for uniqueness across all rows except the ones that belong to current user. and don't forget to change signature of IsUserEsists action result to receive Identity like
public ActionResutl IsUserExists(string UserName, int Identity)
{
}
Can't you just change server side validation method to something like:
public ActionResult IsUserExists(string userName)
{
if (!UserService.UserNameExists(userName) || (CurrentUser.UserName == userName))
{
return "Yeah. Is it valid.";
}
}
You have current user, because he is logged in. As long as user can only edit his data, this will work.
This is one place where buddy metadata falls short.
Edit/Add scenarios require their own view models. One size fits all scenario validation attributes only work in very trivial business CRUD apps. Add and Edit actions happen in totally different contexts and are only transiently related. This concept is very similar to the DDD bounded context idea.