Saturday, January 30, 2010

Favorite Extension Methods




I thought I’d share some of my favorite extension methods I use regularly. I’ll go through a few extensions for MailMessage, HtmlHelper, and DirectoryEntry (for Active Directory).

MailMessage Extension (only 1)

    public static class MailMessageExtensions
{
public static void Send(this MailMessage mailMessage)
{
#if (DEBUG)
mailMessage.To.Clear();
mailMessage.To.Add(
WebConfig.FromEmail);
#endif

var sc = new SmtpClient();
sc.Send(mailMessage);
}
}

HtmlHelper (only 1)

        public static string DivSuccessMessage(this HtmlHelper html, string successMessage)
{
if (html.ViewData.ModelState.IsValid && html.ViewData["success"] != null)
return "<div class=\"success-message\">" + successMessage + "</div>";

return "";
}

I created this extension to act similar to the ValidationSummary extension. Basically it checks for ViewData[“success”] and that the model state is valid then returns the sucess message, otherwise it returns nothing.


DirectoryEntry


Need a property? Here you go, just give me the name. (I also use an enum for our AD schema too to pass in the propertyName)

public static string GetProperty(this DirectoryEntry entry, string propertyName)
{
if (entry.Properties[propertyName] == null || entry.Properties[propertyName].Value == null)
return null;

return entry.Properties[propertyName].Value.ToString();
}

Need to add a property? Done…it’ll even commit the changes.

public static void AddProperty(this DirectoryEntry entry, string propertyName, string propertyVal, bool commitChange)
{
if (entry.Properties[propertyName] == null || propertyVal == null)
return;

entry.Properties[propertyName].Value = propertyVal;
if (commitChange)
entry.CommitChanges();
}

I have a couple more for adding properties…one that adds just a property and commits without asking and then one that adds multiple properties at once.

public static void AddProperty(this DirectoryEntry entry, string propertyName, string propertyVal)
{
AddProperty(entry, propertyName, propertyVal,
true);
}

public static void AddProperties(this DirectoryEntry entry, params Func<string, string>[] values)
{
foreach (var func in values)
AddProperty(entry, func.Method.GetParameters()[
0].Name, func(null), true);
}

Here’s one to enable an account

public static void EnableAccount(this DirectoryEntry entry)
{
if (!ValidUserAccount(entry))
return;

entry.Properties[
Attributes.userAccountControl].Value = GetCurrentUserAccountControl(entry) & Flags.ADS_UF_NORMAL_ACCOUNT;
entry.CommitChanges();
}

private static int GetCurrentUserAccountControl(DirectoryEntry entry)
{
int currentVal;
return !int.TryParse(entry.Properties[Attributes.userAccountControl].Value.ToString(), out currentVal) ? 0 : currentVal;
}

private static bool ValidUserAccount(DirectoryEntry entry)
{
return entry.SchemaClassName.Equals("user", StringComparison.CurrentCultureIgnoreCase);
}

Here’s one to disable an account

public static void DisableAccount(this DirectoryEntry entry)
{
if (!ValidUserAccount(entry))
return;

entry.SetPassword(
"SomeDefaultPassword");
entry.Properties[
Attributes.userAccountControl].Value = GetCurrentUserAccountControl(entry) | Flags.ADS_UF_ACCOUNTDISABLE;
entry.CommitChanges();
}

Another one to reset password

public static void SetPassword(this DirectoryEntry entry, string password)
{
if (!ValidUserAccount(entry))
return;

entry.Invoke(
"SetPassword", new object[] {password});
entry.CommitChanges();
}

There you go…a few extensions that I use and thought I’d share. I know you all have some good ones so feel free to share.


Thanks for reading!


Shout it

kick it on DotNetKicks.com

Friday, January 29, 2010

Getting Started with fluentHtml




I mentioned a couple posts ago that I’d blog about how to get setup with fluentHtml, which is packaged with the MvcContrib project. Let’s get started…

Step 1:
Reference MvcContrib & MvcContrib.FluentHtml in your project after downloading the MvcContrib project.

Step 2:
Create a new base page that inherits from the ModelViewPage<T> in MvcContrib.FluentHtml. It’ll end up looking like this:

    public class BaseViewPage<T> : MvcContrib.FluentHtml.ModelViewPage<T> where T : class
{
}

Step 3:
So in your aspx page, you’ll inherit from the BaseViewPage<T> like this:

<%@ Page Language="C#" Inherits="Core.UI.Model.BaseViewPage<PersonView>" %>

PersonView is the sample view model I’m using for this post and it looks something like this:

    public class PersonView
{
public string Name { get; set; }
public string StreetAddress { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string PasswordSample { get; set; }
public string TextAreaSample { get; set; }
public bool CheckboxSample { get; set; }
}

Just something basic so you can see some of the possibilities.


Step 4:
In the <pages><namespaces> section of the web.config, you can add the namespaces so you don’t have to reference them in your aspx pages. It’ll look like this:

    <add namespace="MvcContrib"/>
<
add namespace="MvcContrib.FluentHtml"/>

Otherwise, you’ll have to use the import at the top of the aspx pages like this:

<%@ Import Namespace="MvcContrib" %>
<%
@ Import Namespace="MvcContrib.FluentHtml" %>

Step 5:
Create your form…here are some samples:

   <p><%=this.TextBox(f=>f.Name).Label("Name: ") %></p>
<
p><%=this.TextBox(f=>f.StreetAddress).Label("Street Address: ") %></p>
<
p><%=this.TextBox(f=>f.City).Label("City: ") %></p>
<
p><%=this.Select(f=>f.State).Options(UnitedStates.StateDictionary) %></p>
<
p><%=this.TextBox(f=>f.PostalCode).Label("Postal Code: ").Styles(display=>"block") %></p>
<
p><%=this.Password(f=>f.PasswordSample).Label("Password Sample: ") %></p>
<
p><%=this.CheckBox(f=>f.CheckboxSample).LabelAfter("Checkbox Sample") %></p>

The above form will create this view:


image


The first 3 are very basic and just have a textbox with a label with the default layout. The other few are examples of how you do certain things with fluentHtml.


A dropdownlist looks like this: <%=this.Select(f=>f.State).Options(UnitedStates.StateDictionary) %>
(See more details on how to add the states in this post)


A Textbox with the label on top looks like this:
<%=this.TextBox(f=>f.PostalCode).Label("Postal Code: ").Styles(display=>"block") %>


A Password looks like this:
<%=this.Password(f=>f.PasswordSample).Label("Password Sample: ") %>


A Checkbox with the label after the box looks like this:
<%=this.CheckBox(f=>f.CheckboxSample).LabelAfter("Checkbox Sample") %>


That’s it for fluentHtml!
Really simple and I love that it’s strongly-typed. I hate this type of code:
<%= Html.TextBox(“Name”, Model.Name) %> However, this will no longer be the case with ASP.NET MVC 2, which is a GREAT thing!


Something else to look into:
Of course if you’re in a rush, you can use something else that the MvcContrib brings to the table and that is Html.InputForm. If you go this route, you’ll need to add all the templates that you want to use from the MvcContrib project’s InputBuilderTemplates into your Shared folder. Then you’d be able to do this in your markup:

  <%=Html.InputForm() %>

And that’ll generate this view:


image


It’s pretty awesome that you can type one line and generate your whole form from the view model and you can change the way it looks in the templates that they provide. These two namespaces MvcContrib.UI.InputBuilder and MvcContrib.UI.InputBuilder.Views are used with the Html.InputForm.


Shout it

kick it on DotNetKicks.com

Thursday, January 28, 2010

Linq to Sql Generic Repository with AutoMapper




We, my teammates and I, have been playing with creating a generic repository for Linq to Sql using AutoMapper. We haven’t used it in production or anything, but I figured I’d blog about it and see if anyone has any comments about it. It’s fun just to toy around sometimes.

A couple of posts ago, I blogged about Func<> and that’s going to play an important part in what I’m about to show you. So basically we started off coding what we would do without generics and then converted that into a generic method. The ending interface looks like this:

public interface ILinq2SqlRepository<TDataContext, TDomainModel, TLinqModel>
where TDataContext : DataContext
{
IList<TDomainModel> GetAll(Func<TDataContext, IQueryable<TLinqModel>> func);
TDomainModel GetById(
Func<TDataContext, TLinqModel> func);
void Save(TDomainModel model, Func<TDataContext, TLinqModel> func);
}

So there is the GetAll and the GetById methods. I’m also working on the Save, but it’s a little more tricky because I believe there’s a bug in Linq to Sql Attach(entity, original) when the primary key is a Guid, but that’s just me :) My Save method right now keeps returning a cannot insert duplicate key error and I’ve Googled it, but to no avail. I’m also not sure how to handle the using(DataContext)…just know it’s a work in progress! Anyhow…


The implementation looks like this:

public class Linq2SqlRepository<TDataContext, TDomainModel, TLinqModel> 
:
ILinq2SqlRepository<TDataContext, TDomainModel, TLinqModel>
where TDataContext: DataContext
{
private readonly TDataContext DataContext;

public Linq2SqlRepository(TDataContext dataContext)
{
DataContext = dataContext;
}

public IList<TDomainModel> GetAll(Func<TDataContext, IQueryable<TLinqModel>> func)
{
var list = Mapper.Map<TLinqModel[], TDomainModel[]>(func.Invoke(DataContext).ToArray());
return list.ToList();
}

public TDomainModel GetById(Func<TDataContext, TLinqModel> func)
{
return Mapper.Map<TLinqModel, TDomainModel>(func.Invoke(DataContext));
}

public void Save(TDomainModel model, Func<TDataContext, TLinqModel> func)
{
using (DataContext)
{
var original = func.Invoke(DataContext);
var entity = Mapper.Map<TDomainModel, TLinqModel>(model);
DataContext.GetTable(
typeof(TLinqModel)).Attach(entity, original);
DataContext.SubmitChanges();
}
}
}

Well here’s the base implementation and it looks a lot easier if you have a good understanding of .Net generics. You can see the common AutoMapper Mapper.Map<> method in there, which is what we’re using to do the left to right mapping and basically we’re just passing in simple Linq commands. So we still have to do our AutoMapper configuration, but my hope is that maybe this post will strike up a good idea in someone else’s head…hopefully!


I thought it’d work best to implement this into a repository by just setting it as a private field like this:

public class SampleRepository : IRepository<DomainPerson>
{
private readonly ILinq2SqlRepository<SampleDataContext, DomainPerson, DataPerson> _repository;
public SampleRepository(string connstring)
{
_repository =
new Linq2SqlRepository<SampleDataContext, DomainPerson, DataPerson>(
new SampleDataContext(connstring));
}

public IList<DomainPerson> GetAll()
{
return _repository.GetAll(x => x.DataPeople);
}

public DomainPerson GetById(Guid id)
{
return _repository.GetById(x => x.DataPeople.SingleOrDefault(y => y.Id == personId));
}

public void Save(DomainPerson person)
{
_repository.Save(person, x => x.DataPeople.SingleOrDefault(y => y.Id == person.Id));
}
}

I went the inheritance route and didn’t really care for it, mainly because it was much uglier in the implementation. So you’ll notice this inherits from a generic IRepository, which could’ve been IDomainPersonRepository that inherits from the generic or was just a plain ole repository. Anyhow, it looks like this:

    public interface IRepository<T>
{
IList<T> GetAll();
T GetById(
Guid id);
void Save(T model);
}

I wanted to show prettier things in the public side of the API like GetById with just Guid instead of pass me an ugly lambda :) (Even though I love the lambdas, a lot of devs don’t care for them) So the users of this API would just reference the IRepository<T>, but I’d actually probably end up renaming to a friendlier name like this:

    public interface IDomainPersonRepository : IRepository<DomainPerson> {}

Then I’d go ahead and inherit my SampleRepository from IDomainPersonRepository…I should really plan these posts out more than I do before typing them so the post is better structured. As I get more practice in, I’ll try to do that for you!


So that’s my thinking on some type of generic repository for Linq to Sql with AutoMapper. Please keep in mind that this was a fly by thing we came up with this afternoon and I thought it was pretty cool. It could definitely use more testing & refactoring!


Let me know if you have any thoughts, questions, or comments.


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

Monday, January 25, 2010

Playing with C# Func<T, TResult> and ADO.NET




I’ve always liked the look of the generic Func and I think the possibilities behind it are awesome. However, it’s usually difficult for me to find a good place to use it. I’m probably just not that used to using it yet and I am missing out on some huge advantages. Ignorance is not bliss sometimes :)

So anyhow, I was playing with the good ole ExecuteScalar & ExecuteNonQuery commands on the IDbCommand interface and came up with something kinda cool. At least I thought so…

I tend to use a DbHelper when I’m doing easy things instead of using NHibernate, Linq2Sql, etc, etc. Well here’s what I started with:

public class DatabaseHelper
{
public static T ExecuteScalar<T>(string connstring, string sql, params IDataParameter[] parameters)
{
using (var oConn = new SqlConnection(connstring))
{
oConn.Open();
using (var oCmd = new SqlCommand(sql, oConn))
{
oCmd.Parameters.AddRange(parameters);
return (T) oCmd.ExecuteScalar();
}
}
}

public static void ExecuteNonQuery(string connstring, string sql, params IDataParameter[] parameters)
{
using (var oConn = new SqlConnection(connstring))
{
oConn.Open();
using (var oCmd = new SqlCommand(sql, oConn))
{
oCmd.Parameters.AddRange(parameters);
oCmd.ExecuteNonQuery();
}
}
}
}


Obviously not pretty and a TON of duplicated code. VERY SMELLY!



So the first thing I did was create a DatabaseCriteria class to help with the number of params I’m passing and it looks like this:

public class DatabaseCriteria
{
public DatabaseCriteria(string connstring, string sqlStatement, params IDataParameter[] parameters)
{
ConnectionString = connstring;
SqlStatement = sqlStatement;
Parameters = parameters;
}
public string ConnectionString { get; set; }
public string SqlStatement { get; set; }
public IDataParameter[] Parameters { get; set; }
}


That’s a little better and it’s easy to modify the existing code that calls my helpers. The next thing I did was create small factories for my connection & command so I wasn’t bound to the Sql Server version and I could easily swap out databases. The builders look like this:

private static IDbConnection BuildConnection(string connstring)
{
return new SqlConnection(connstring);
}

private static IDbCommand BuildCommand(string sqlStatement, IDataParameter[] parameters, IDbConnection connection)
{
var command = new SqlCommand(sqlStatement, (SqlConnection)connection);
command.Parameters.AddRange(parameters);
return command;
}


Obviously I’m using some SqlCommand features like the AddRange and I’m casting straight to the SqlConnection, but that code is only in one spot and it’d be easy to setup an IoC tool or something. I want to keep this blog simple though, so I’ll leave it as is for now.



Okay, so now let’s get to the fun stuff! Here’s my new ExecuteSql generic method:

private static T ExecuteSql<T>(DatabaseCriteria dbCriteria, Func<IDbCommand, T> func)
{
using (var oConn = BuildConnection(dbCriteria.ConnectionString))
{
oConn.Open();
using (var oCmd = BuildCommand(dbCriteria.SqlStatement, dbCriteria.Parameters, oConn))
{
return func.Invoke(oCmd);
}
}
}


Okay, so this accepts a DatabaseCriteria object and a generic Func that invokes an action on IDbCommand and returns T. It also takes advantage of the two factories I made and obviously the using statement.


Updated: 1/26/2010 8:16PM
Thanks to the comments of Thilak Nathen, I’ve made an improvement to the ExecuteScalar<T> method. Before him bringing it to my attention, my code could’ve thrown the dreaded “Object reference not set to an instance of an object” message. I think we all have grown to hate that message. Sadly it’s easy to check for and we sometimes just look over it. If you’re interested, the ExecuteScalar before the update was just one line and it was: return ExecuteSql(dbCriteria, x => (T) x.ExecuteScalar());


Thanks Thilak!


Now my DatabaseHelper looks like this:

public class DatabaseHelper
{
public static T ExecuteScalar<T>(DatabaseCriteria dbCriteria)
{
var result = ExecuteSql(dbCriteria, x => x.ExecuteScalar());
return (result is T) ? (T)result : default(T);
}

public static void ExecuteNonQuery(DatabaseCriteria dbCriteria)
{
ExecuteSql(dbCriteria, x => x.ExecuteNonQuery());
}

private static T ExecuteSql<T>(DatabaseCriteria dbCriteria, Func<IDbCommand, T> func)
{
using (var oConn = BuildConnection(dbCriteria.ConnectionString))
{
oConn.Open();
using (var oCmd = BuildCommand(dbCriteria.SqlStatement, dbCriteria.Parameters, oConn))
{
return func.Invoke(oCmd);
}
}
}

private static IDbConnection BuildConnection(string connstring)
{
return new SqlConnection(connstring);
}

private static IDbCommand BuildCommand(string sqlStatement, IDataParameter[] parameters, IDbConnection connection)
{
var command = new SqlCommand(sqlStatement, (SqlConnection)connection);
command.Parameters.AddRange(parameters);
return command;
}
}


I think there could be a little more clean up here, but basically I think it’s pretty clean. There is pretty much zero code duplication and no dependencies on implementations other than in my two builders. You should also notice that everything is private other than the ExecuteScalar and the ExecuteNonQuery because I only want people to use those two methods. Anyhow, I like it! Hopefully you do too.



Thanks for reading!


Shout it

kick it on DotNetKicks.com

Saturday, January 23, 2010

Basic jQuerying




So a few of my co-workers were wanting to know more about jQuery, so I thought I’d post an entry on the topic…a really basic intro to get people thinking and starting to use it.

There are a few things I love about jQuery and they are…

  1. You can query all your markup
  2. If it’s something with the client-side, there’s a plugin for it!
  3. It’s easy and fun to use

So let’s get started with the most common structure:

$(document).ready(function() {
$(
selectorhere).whateverfunction();

});

You may be wondering what the $ represents and the answer is…it’s a shortcut! jQuery(document) and $(document) are the same thing.


Okay so why do you call .ready all the time? Well one of the nice things about jQuery is that it knows when the DOM (Document Object Model) has loaded so between the brackets will run as soon as that happens. It works as a safety net basically.


The “selectorhere” represents what you want to query the DOM for basically. You can have all types of selectors, but I’ll list a few of the most common that I use.



  1. The class selector $(‘div.classname’)
    so this will search the DOM for anything marked up like this: <div class=”classname”></div>

  2. The id selector $(‘div#maincontent’)
    This will select the div with an id of maincontent like this: <div id=”maincontent”></div>

  3. The html tag selector $(‘a’)
    This will select all the anchors on the page like this: <a href=””></a> or <a name=””></a>

  4. The attribute contains selector $(‘a[href*=something]’)
    This will select all anchors with an href that contains the word something like this: <a href=”http://testsomething.com”></a>

Those are all the basic selectors I use, but you can read more about all the different types at jquery.com


Once you’ve selected what you want, you can do stuff to it/them. For example, say I wanted to add the jQuery datepicker to all textboxes with a class name of “date”. (Note: the jQuery datepicker is part of the jquery-ui library)


Alright so that jQuery code would look like this:

$(document).ready(function() {
$(
'input:text.date').datepicker();
});

So here I’m using the jQuery selector to say get me all inputs of type text with a class name of date. Just like the first little sample from above…really easy to use.


You can see more examples on these posts:



As always, thanks for reading!

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...