Showing posts with label Castle Validators. Show all posts
Showing posts with label Castle Validators. Show all posts

Friday, March 05, 2010

Contact Form with ASP.NET MVC, Castle Validation, & fluentHtml




Here’s another little tutorial for those of you new to MVC &/or fluentHtml. I figure I’ll do these little tutorials until I find a new project to work on. I do have a couple of ideas…so we’ll see how those turn out.

Let’s get started.

We’ll start with the view model class again like last week. By the way, if you’re not familiar with the way I setup my MVC projects, see this post.

public class ContactView
{
[
ValidateNonEmpty("Name")]
public string Name { get; set; }
[
ValidateNonEmpty("Email"), ValidateEmail("Valid Email")]
public string Email { get; set; }
public string Subject { get; set; }
[
ValidateNonEmpty("Message")]
public string Message { get; set; }
}

The ValidateNonEmpty and ValidateEmail are attributes from the Castle project and I’m passing in the error message I want displayed if invalid. Alrighty, let’s setup our controller action and the view (html).

Controller Action:

public class ContactController : Controller
{
public ActionResult Index()
{
return View(new ContactView());
}
}

View/HTML Markup

<%@ Page Title="Contact Us" Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="MvcContrib.FluentHtml.ModelViewPage<ContactView>" %>

<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<
h2>Contact Us</h2>
<% using(Html.BeginForm("Index", "Contact", FormMethod.Post)) {%>
<%
=Html.DivSuccessMessage("Message sent successfully!")%>
<%
=Html.DivValidationSummary("Please see the items below:")%>
<fieldset>
<
legend>Proposal Form</legend>
<%=this.TextBox(f => f.Name).Label("Name:")%>
<%
=this.TextBox(f => f.Email).Label("Email:")%>
<%
=this.TextBox(f => f.Subject).Label("Subject:")%>
<%
=this.TextArea(f => f.Message).Label("Message:")%>
<%
=Html.AntiForgeryToken() %>
<%
=this.SubmitButton("Send").Attr("accesskey", "S").Class("sb") %> All fields are required.
</
fieldset>
<% } %>
</asp:Content>

This is a simple form with fluentHtml. If you need a tutorial on fluentHtml, here’s a post on it. You should notice that this page inherits from the MvcContrib ModelViewPage with our ContactView from above being passed in. I typically create my own base page that inhertis from the MvcContrib one, but to make this post easier, I just inherit straight from their’s.

Okay, let’s get to the meet where we accept the post in the controller.

[AcceptVerbs(HttpVerbs.Post), ValidateModel(typeof(ContactView)), ValidateAntiForgeryToken]
public ActionResult Index(ContactView form)
{
if (!ModelState.IsValid)
return View(form);

try
{
var notificationService = DI.EmailNotificationService(new EmailNotification(form));
notificationService.Notify();

Success();
}
catch (NotificationException)
{
ModelState.AddModelError(
"notifyerror"
, "Unfortunately, something went wrong with the message delivery. Please try again.");
}

return View(form);
}

Okay, so we’re only accepting a post, we’re validating our model with a validation filter, and validating the anti-forgery token. I’m also accepting my ContactView model. If the model state isn’t valid, I return the model back to the view. Otherwise, I try to create a new instance of EmailNotificationService (which returns an INotificationService) then I call the Notify(). If I don’t receive a NotificationException, then I call Success() on my SmartController (which is what this controller inherits from) Success(); simply does this: ViewData["success"] = ""; You can read more about it in this post. If the Notify() bombs, we add a model error and then finally we return the form to the view. If you wanted to clear out the form, you’d put return View(new ContactView()) right after the Success() call.

So what does the INotificationService look like? Well, this:

public interface INotificationService
{
void Notify();
}

The implementation looks like this:

public class EmailNotificationService : INotificationService
{
private readonly IEmailNotification _emailNotification;

public EmailNotificationService(IEmailNotification emailNotification)
{
_emailNotification = emailNotification;
}

public void Notify()
{
using (var mail = new MailMessage())
{
mail.To.Add(_emailNotification.To);
mail.From =
new MailAddress(_emailNotification.From);
mail.Subject = _emailNotification.Subject;
mail.Body = _emailNotification.Body;
mail.IsBodyHtml =
true;

try
{
mail.Send();
}
catch (SmtpException)
{
throw new NotificationException();
}
}
}
}

NOTE: You can also try using AutoMapper to map to the MailMessage, but for whatever reason, it was not working out for me. I send Jimmy and email about it, but he’s busy enough and it’s not that big a deal to do the left=right thing every once in a while :)

My IEmailNotification looks like this:

public interface IEmailNotification
{
string To { get; }
string From { get; }
string Subject { get; }
string Body { get; }
}

I’ll show the implementation in a sec. First I wanted to show what the NotificationException looks like…

public class NotificationException : Exception
{
}

That’s it…I can adjust as needed, but for this…there’s no reason really. I just want to be able to catch the type in my controller. Yes you could do catch(SmtpException) in the controller, but what if your next implementation of INotificationService doesn’t use smtp and you have catch(SmtpException) spread all through your other code? It wouldn’t be a good thing. Let’s keep truckin…

Here’s the implementation of IEmailNotification:

public class EmailNotification : IEmailNotification
{
private readonly ContactView _view;

public EmailNotification(ContactView view)
{
_view = view;
}

public string To
{
get { return "email@email.com"; }
}

public string From
{
get { return _view.Email; }
}

public string Subject
{
get { return _view.Subject; }
}

public string Body
{
get { return _view.Message; }
}
}

You should pull email@email.com from some type of config file since it could potentially change often. What’s cool about this is that now I could have different versions for nighttime daytime or certain months or whatever…I don’t know why you’d ever do that, but it’s getting late and I can’t think of better examples :)

Anyhow…you can also customize the body here and not have to worry about formatting in your controller. You could do something like this for the Body:

public string Body
{
get
{
var body = new StringBuilder();
body.AppendFormat(
"Date Message Sent: {0}", DateTime.Now);
body.AppendFormat(
"Sent from IP: {0}", HttpContext.Current.Request.UserHostAddress);
body.AppendFormat(
"Browser Used: {0} v{1}", HttpContext.Current.Request.Browser.Browser,
HttpContext.Current.Request.Browser.Version);
return _view.Message;
}
}

I hope I didn’t leave anything out…if I did, please let me know!

Thanks for reading!


Shout it

kick it on DotNetKicks.com

Sunday, February 28, 2010

Authentication with Active Directory, ASP.NET MVC, & fluentHtml




I figure since people are starting to really look into MVC and are realizing that it’s going to be around for a while, they’re going to need some decent samples when researching how to do things. I’m hoping this particular post will possibly be one of those examples. I had the same thought when I wrote the Security Questions with ASP.NET MVC & fluentHtml post.

Let’s get started with the view model class for the sign in page. By the way, if you’re not familiar with the way I setup my MVC projects, see this post.

public class SignInView
{
[
ValidateNonEmpty("Username is required.")]
public string Username { get; set; }
[
ValidateNonEmpty("Password is required.")]
public string Password { get; set; }
}

Really simple. The ValidateNonEmpty is an attribute from the Castle project and I’m passing in the error message I want displayed if invalid.

Okay, so let’s go ahead and pass in this view model to our actual view from the AuthenticationController. This will look like this:

public ActionResult Index()
{
return View(new SignInView());
}

Now we’ll create our actual view (html):

<%=Html.DivValidationSummary("All fields are required.") %>
<form action="/authentication/index" method="post">
<
fieldset>
<
legend>Sign In</legend>
<
p><%=this.TextBox(f => f.Username).Label("Username: ")%></p>
<
p><%=this.Password(f => f.Password).Label("Password: ")%></p>
<%=Html.AntiForgeryToken() %>
<%=Html.SubmitButton("Sign In", cssclass=>"sb", accesskey=>"S") %>
</
fieldset>
</
form>

This is our basic html setup with fluentHtml added to it. If you need a tutorial on fluentHtml, here’s a post on it. Basically, I’m using my htmlHelper for a DivValidationSummary, I’m calling the index action on the authentication controller, then I’m setting up my textboxes with fluentHtml, using the antiforgerytoken to prevent csrf, and I’m using my submit button that I blogged about before this post.

Now let’s look at the action that’s being called by the form above.

[AcceptVerbs(HttpVerbs.Post), ValidateModel(typeof(SignInView)), ValidateAntiForgeryToken]
public ViewResult Index(SignInView form)
{
if (!ModelState.IsValid)
return View("index", form);

IUser user = DependencyRegistrar.With<string, IUser>(form.Username);
bool passwordMatches = _authenticationService.PasswordMatches(user, form.Password);

if (passwordMatches)
{
//Sign In – Write Cookie & Redirect most likely through a UserSession
}

ModelState.AddModelError(
"SignIn", "Invalid credentials");
return View("index", form);
}

Okay, so you can see I’m accepting only post, I’m validating the model, and I’m validating the token. I’m also accepting my SignInView model. If the model state is not valid I return the model back to the view. Otherwise, I get an instance of user with my username and then I call my authenticationService. If passwordMatches, sign in and return, otherwise add an error and return.

So let’s look at my IUser real quick. It’s really simple:

public interface IUser
{
string Username { get; set; }
}

Think my AuthenticationService is much more difficult? Of course not!

public interface IAuthenticationService
{
bool PasswordMatches(IUser user, string password);
}

By the way, I’m accepting an instance of IAuthenticationService in the constructor of the controller like so:

public AuthenticationController(IAuthenticationService authenticationService)
{
_authenticationService = authenticationService;
}

I’m using StructureMap to know what to pass in to the constructor. Okay, so my AuthenticationService implementation looks like this:

public class AuthenticationService : IAuthenticationService
{
private readonly IActiveDirectorySettings _adSettings;

public AuthenticationService(IActiveDirectorySettings activeDirectorySettings)
{
_adSettings = activeDirectorySettings;
}

public bool PasswordMatches(IUser user, string password)
{
var authenticated = false;
var domainAndUsername = _adSettings.DomainName + "\\" + user.Username;
var entry = new DirectoryEntry("LDAP://" + _adSettings.LdapPath, domainAndUsername, password);

try
{
var bindToNativeObjectToForceAuthentication = entry.NativeObject;
authenticated =
true;
}
catch (COMException)
{
}

return authenticated;
}
}

Now my IActiveDirectoryCredentials looks like this:

public interface IActiveDirectorySettings
{
string DomainName { get; }
string LdapPath { get; }
}

That’s basically it. There’s not a whole lot to an authentication process, but thought I’d share anyhow.

Thanks for reading!


Shout it

kick it on DotNetKicks.com

Wednesday, January 27, 2010

Security Questions with ASP.NET MVC & fluentHtml




Have you ever needed to create a screen to ask a user to select security questions? Well, I recently had to create this screen and I thought I’d share the experience.

I guess I’ll start with the view model.

public class CreateSecurityQuestionsView
{
public IList<SelectListItem> QuestionList
{
get { return DI.SecurityQuestionService().GenerateSecurityQuestions(); }
}

[
ValidateNonEmpty("Username was not found")]
public string Username { get; set; }




[
ValidateNonEmpty("")]
[
ValidateNotSameAs("SecondQuestionId", "Question 1 = Question 2")]
[
ValidateNotSameAs("ThirdQuestionId", "Question 1 = Question 3")]
public string FirstQuestionId { get; set; }

[
ValidateNonEmpty("Answer 1 is Required")]
public string FirstAnswer { get; set; }

[
ValidateNonEmpty("")]
[
ValidateNotSameAs("FirstQuestionId", "Question 2 = Question 1")]
[
ValidateNotSameAs("ThirdQuestionId", "Question 2 = Question 3")]
public string SecondQuestionId { get; set; }

[
ValidateNonEmpty("Answer 2 is Required")]
public string SecondAnswer { get; set; }

[
ValidateNonEmpty("")]
[
ValidateNotSameAs("FirstQuestionId", "Question 3 = Question 1")]
[
ValidateNotSameAs("SecondQuestionId", "Question 3 = Question 2")]
public string ThirdQuestionId { get; set; }

[
ValidateNonEmpty("Answer 3 is Required")]
public string ThirdAnswer { get; set; }
}

So my view has a QuestionList, which gets all the questions for the end-user to select. I’ll populate the dropdownlists with this property in a bit. I used the goodsecurityquestions.com website to gather my questions and I’m using 15 in the selection. The other properties are pretty standard and the validation attributes are Castle Validators. I’m not a fan of the way the ValidateNotSameAs worked out for me, but it does the job.


Okay, let’s take a look at the HTML.

<%=Html.DivValidationSummary("All three questions are required and should be unique")%>
<form action="/Account/CreateSecurityQuestions/" method="post" id="step5form">
<
fieldset>
<
legend>Create Security Questions</legend>
<
p><%=this.Select(f => f.FirstQuestionId)
.Options(Model.QuestionList)
.Label(
"Security Question 1: ")
.Selected(Model.FirstQuestionId)
%></p>

<
p><%=this.TextBox(f => f.FirstAnswer).Label("Answer 1: ")%></p>

<
p><%=this.Select(f => f.SecondQuestionId)
.Options(Model.QuestionList)
.Label(
"Security Question 2: ")
.Selected(Model.SecondQuestionId)
%></p>

<
p><%=this.TextBox(f => f.SecondAnswer).Label("Answer 2: ")%></p>

<
p><%=this.Select(f => f.ThirdQuestionId)
.Options(Model.QuestionList)
.Label(
"Security Question 3: ")
.Selected(Model.ThirdQuestionId)
%></p>

<
p><%=this.TextBox(f=>f.ThirdAnswer).Label("Answer 3: ") %></p>
<%=this.Hidden(f=>f.Username) %>
<%
=Html.AntiForgeryToken() %>
<div style="text-align: right"><%=Html.SubmitButton("Finish", "sb", "S") %></div>
</
fieldset>
</
form>

So you can see here, I’m using fluentHtml and  you can see the view model from above spread all through the markup. You should notice the Model.QuestionList three different times in the above markup in the Options() for the Select(). In order to use fluentHtml, you’ll need to inherit from the MvcContrib.FluentHtml.ModelViewPage<TModel>. I plan on doing a post on fluentHtml soon, which will go through the configuration and usage…etc.


The controller is really basic and looks like this:

[AcceptVerbs(HttpVerbs.Post), ValidateModel(typeof(CreateSecurityQuestionsView)), ValidateAntiForgeryToken]
public ActionResult CreateSecurityQuestions(CreateSecurityQuestionsView securityQuestionsView)
{
if (!ModelState.IsValid)
return View("Step5", securityQuestionsView);

_registrationService.CreateSecurityQuestions(
Mapper.Map<CreateSecurityQuestionsView, AccountInformation>(securityQuestionsView));

return RedirectToAction("Summary");
}

Alrighty, so the CreateSecurityQuestions action is post only, it uses the ValidateModel filter that I got from CodeCampServer (I think), and it uses the ValidateAntiForgeryToken. You can read more about the ValidateAntiForgeryToken on Phil Haack’s post. Obviously the action accepts the CreateSecurityQuestionsView and then it checks to verify the ModelState is valid, if not, it returns the view. Then I’m using AutoMapper to map the view model to my AccountInformation object and then I redirect to the summary action. The _registrationService is passed into the controller via the constructor.


I did consider doing a loop on the security questions and answers, but I thought the most I’d ever have is 5 in the view and as long as it’s not a set number in my domain I’m alright with it. Basically, what I’m saying is don’t put securityQuestion1, 2, 3 etc in your domain model, allow it to grow to how many ever security questions your end-user wants to answer. The reason we’re using three is because we require our registered users to answer three and then they can add more later once they’ve completed the registration process.


I think that about covers everything. Please comment if you’d like more details on anything.


Thanks for reading!


Shout it

kick it on DotNetKicks.com

Thursday, January 21, 2010

ASP.NET MVC with Castle Validators, fluentHtml, and jQuery




Okay, so you remember this post about changing the default textbox value with jQuery? Well, I ran into a SNAFU because my required validation wasn’t working on the controller side of the house. If people submitted the form with “street address”, “city”, or “postal code”, it would post. Not a good thing! Granted I could add some jQuery validation to check the fields etc, but I like validating my input knowing that JavaScript is easily disabled…you should too :)

Just so you don’t have to flip to the other post, here’s the end-result I was looking for in the previous post:
[image3.png]

So I thought okay well I’ll put the ValidateNotSameValue() attribute on my view model and it will be good. Well then I thought, what if I wanted to put “ZIP code” instead of “postal code”? I’d have to change the view and the view model and I don’t like them being that good of friends, so I came up with a solution and here it is…

Let’s take the Street Address textbox from the first post and create a ValidateNotSameValue() attribute on it. Now it looks like this:

private string _streetAddress;

[
ValidateNonEmpty(ViewErrorMessages.InvalidStreetAddress)]
[
ValidateNotSameValue(typeof(string), ViewDefaults.StreetAddress, ViewErrorMessages.InvalidStreetAddress)]
public string StreetAddress
{
get { return _streetAddress ?? ViewDefaults.StreetAddress; }
set { _streetAddress = value; }
}

So this says, ValidateNonEmpty and return the InvalidStreetAddress message. On a side note, I started putting my error messages in a separate class or sometimes an XML file a while back when I sat in on a Paul Sherrif talk at a VS Live event. It saves a lot of time and it’s strongly-typed, which I always like. Let’s keep on truckin…Next attribute says ValidateNotSameValue as ViewDefaults.StreetAddress and if they do equal, show the InvalidStreetAddress message. Basically that’s all there is to my trick…not that cool, but kind of I thought :)


At this point, the ViewDefaults class looks like this:

    public class ViewDefaults
{
public const string StreetAddress = "street address";
}

The main reason I wanted to go this route is because I show that same text in the view like this:

<%=this.TextBox(f => f.StreetAddress)
.Label(
"Street Address: ")
.Value(Model.StreetAddress)
.Title(
ViewDefaults.StreetAddress)%>

So in order to get my jQuery to switch out the default value and put it back if nothing has been done, then I need to define the title. The reason I don’t set the Value to ViewDefaults.StreetAddress on the view and not in the view model is because when I return the view, the default would override the actual entry that failed validation. So the value HAS to match the actual view model values being passed around. (That doesn’t sound confusing at all??? Sorry bout that)


The other cool thing about having a ViewDefaults class is that you can set the default value for starter values or in dropdownlists, etc. Here’s an example of it being used in the DateOfBirth property on my view model.

        public DateTime DateOfBirth
{
get { return (_dateOfBirth == DateTime.MinValue) ? ViewDefaults.DateOfBirth : _dateOfBirth; }
set { _dateOfBirth = value; }
}

We know the default value of DateTime = DateTime.MinValue so obviously we wouldn’t want to display “1/1/0001” as a default value for a birth date. So the cool thing about the ViewDefaults is that we can set a default value for DateOfBirth and it looks like this:

        public static readonly DateTime DateOfBirth = DateTime.Now.AddYears(-10);

I wanted my default DateOfBirth to be right now minus 10 years. Now in my view, I can trust that my end-user will never see “1/1/0001”.


Anyhow, thought I’d share…there may be a better way, but I didn’t find one on my Google search. If you do find one, please share!


Thanks for reading!


Shout it

kick it on DotNetKicks.com

Related Posts Plugin for WordPress, Blogger...