views:

1562

answers:

5

I've got a view model like this:

public class SignUpViewModel
{
    [Required(ErrorMessage = "Bitte lesen und akzeptieren Sie die AGB.")]
    [DisplayName("Ich habe die AGB gelesen und akzeptiere diese.")]
    public bool AgreesWithTerms { get; set; }
}

The view markup code:

<%= Html.CheckBoxFor(m => m.AgreesWithTerms) %>
<%= Html.LabelFor(m => m.AgreesWithTerms)%>

The result:

No validation is executed. That's okay so far because bool is a value type and never null. But even if I make AgreesWithTerms nullable it won't work because the compiler shouts

"Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions."

So, what's the correct way to handle this?

+1  A: 

"Required" is the wrong validation, here. You want something akin to "Must have the value true," which is not the same as "Required". What about using something like:

[RegularExpression("^true")]

?

Craig Stuntz
If a boolean must always be / is required to be true, it's not even necessary in your code. If the Required attribute is there to help with the DB level "NOT NULL" statement, it's not needed because you're guaranteed to have either a true or false value.
Chris F
@Chris, it will be on your edit model, but not on your entities. Generally, you shouldn't bind directly to entities.
Craig Stuntz
@Craig, agreed on not directly binding. However, if your domain model object (entity) has a property that is required to always be true, then it's not a property that is of any use, right?
Chris F
Right, but that isn't what he proposed here.
Craig Stuntz
Craig Stuntz: Not working.
Peter Stegnar
@Peter: Examine what the POST contains. Write a regex which is better than my first guess.
Craig Stuntz
+5  A: 

I got it by creating a custom attribute:

public class BooleanRequiredAttribute : RequiredAttribute 
{
    public override bool IsValid(object value)
    {
        return value != null && (bool) value;
    }
}
asp_net
+1 for posting your solution, but I still think "Required" is the wrong name. I'd call it `BooleanRequireTrueAttribute` or something.
Craig Stuntz
Yes, I agree with you. I'll rename it to BooleanRequireToBeTrueAttribute
asp_net
A: 

My solution is this simple custom attribute for boolean values:

public class BooleanAttribute : ValidationAttribute
{
    public bool Value
    {
        get;
        set;
    }

    public override bool IsValid(object value)
    {
        return value != null && value is bool && (bool)value == Value;
    }
}

Then you can use it like this in your model:

[Required]
[Boolean(Value = true, ErrorMessage = "You must accept the terms and conditions")]
[DisplayName("Accept terms and conditions")]
public bool AcceptsTerms { get; set; }
brainnovative
+5  A: 

My Solution is as follows (it's not much different to the answers already submitted, but I believe it's named better):

/// <summary>
/// Validation attribute that demands that a boolean value must be true.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class MustBeTrueAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        return value != null && value is bool && (bool)value;
    }
}

Then you can use it like this in your model:

[MustBeTrue(ErrorMessage = "You must accept the terms and conditions")]
[DisplayName("Accept terms and conditions")]
public bool AcceptsTerms { get; set; }
s1mm0t
+1: Searched, found the post, picked the best answer (you're right, yours is named best), cut, pasted, refresh, problem solved. Less than 2 minutes...sweet
Rob
A: 

I got the same problem. How can I apply your solution exactly in this situation?

I've create a partial class then I apply this attribute into my partial class but It doesn't work.

Here my code

Your solution:

namespace Framework
{
    /// <summary>
    /// Validation attribute that demands that a boolean value must be true.
    /// </summary>
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
    public class MustBeTrueAttribute : ValidationAttribute
    {
        public override bool IsValid(object value)
        {
            return value != null && value is bool && (bool)value;
        }
    }

} 

Below is my partial class (A : an example object).

using System.ComponentModel.DataAnnotations;

namespace Framework.Models
{
    [MetadataType(typeof(AValidation))]
    public partial class A{ }

    public class AValidation 
    {
        [MustBeTrue(ErrorMessage = "Value must be true")]
        public bool isHot { get; set; }
    }
}

Below is an extract of my HTML code

<label>
Is Hot
<%=Html.ValidationMessageFor(model => model.isHot)%>
</label>
<%=Html.CheckBoxFor(model => model.isHot, new {@class="input" })%>

It always rase error when I am trying to run it. Below is an extraction of error message.

Cannot convert lambda expression to delegate type 'System.Func<Framework.Models.A,bool>' because some of the return types in the block are not implicitly convertible to the delegate return type

Cannot implicitly convert type 'bool?' to 'bool'. An explicit conversion exists (are you missing a cast?)

Please help me?

Thanks in advance.

nvtthang