I am using MVC 3 with Razor. I can't figure out how to code a string extension regex to take this:
This_is_some_text
to display:
This is some text
I set up some enums for a drop down list, so they appear thusly (obviously I can't create an enum with a space):
public enum MyProperty
{
This_is_some_text,
This_is_some_other_text
}
I just cannot figure out the regex is to do what I want if I am doing this:
public static string EnumToDisplay(this string str)
{
return Regex.Replace(str, "[What is the regex I should use?]");
}
As a bonus for me I would also like to add a period "." to the end of the enum. The reason for this is that I have OCD and my enums are taking the form of short sentences. :)
Thanks!
Why not use String.Replace() for this? RegEx seems a bit overkill.
public static string EnumToDisplay(this string str)
{
return str.Replace('_', ' ') + ".";
}
Why do you want to use regular expressions? A very wise man once said, I quote:
Some people, when confronted with a problem, think "I know, I'll use
regular expressions." Now they have two problems.
How about using the [Display] attribute which is kinda designed exactly for this purpose:
public enum MyProperty
{
[Display(Name = "This is some super text")]
This_is_some_text,
[Display(Name = "And this is some other text")]
This_is_some_other_text
}
and then writing a custom Html helper:
public static class HtmlExtensions
{
public static IHtmlString DisplayForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
{
if (!typeof(TProperty).IsEnum)
{
throw new ArgumentException("sorry this helper is inteded to be used with enum types");
}
var model = htmlHelper.ViewData.Model;
if (htmlHelper.ViewData.Model == null)
{
return MvcHtmlString.Empty;
}
var field = typeof(TProperty).GetField(expression.Compile()(htmlHelper.ViewData.Model).ToString());
if (field == null)
{
return new HtmlString(htmlHelper.Encode(htmlHelper.ViewData.Model.ToString()));
}
var display = field.GetCustomAttributes(typeof(DisplayAttribute), true).FirstOrDefault() as DisplayAttribute;
if (display == null)
{
return new HtmlString(htmlHelper.Encode(htmlHelper.ViewData.Model.ToString()));
}
return new HtmlString(htmlHelper.Encode(display.Name));
}
}
So now assuming you have a view model:
public class MyViewModel
{
public MyProperty Foo { get; set; }
}
and a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
Foo = MyProperty.This_is_some_other_text
};
return View(model);
}
}
you could use the custom helper we just wrote in the view to display a user friendly text that we might have associated to an ugly enum. Hey, now you could even have this working with globalization and multiple languages using resources:
#model MyViewModel
#Html.DisplayForEnum(x => x.Foo)
I do not know about asp.net - but there should be a really simple method that replaces one character with another char. Like:
String.replace( myString, '_',' ' );
You can use the replacement pattern which is also called substitution.
You can find graet info here:
http://msdn.microsoft.com/en-us/library/ewy2t5e0.aspx
Good luck
Related
In the following code, the
I'd like to improve the performance by putting the RegExp object somewhere, but I can't figure out how to do the nest.
#ValidatorConstraint()
export class RegExp implements ValidatorConstraintInterface {
validate(kana: string, args: ValidationArguments) {
const str = new RegExp(/^[ァ-ヶー]+$/)
return str.test(kana)
}
defaultMessage(args: ValidationArguments) {
return 'Text should be'
}
}
thanks
If you need regexp only - simply use a built-in Matches validator:
#Matches(/^[ァ-ヶー]+$/)
public field: string;
In this case it will reuse regexp on every validation.
I thought of it this way.
const regexp = new RegExp(/^[ァ-ヶー]+$/)
#ValidatorConstraint()
export class RegExp implements ValidatorConstraintInterface {
validate(kana: string, args: ValidationArguments) {
return regexp.test(kana)
}
defaultMessage(args: ValidationArguments) {
return 'Text should be'
}
}
I am trying to use conventions in my unit tests which make use of AutoFixture. I have a Password value object as shown:
public class Password : SemanticType<string>
{
private int _daysPasswordValid;
public Password(string password) : base(IsValid, password)
{
Guard.NotNullOrEmpty(() => password, password);
Guard.IsValid(() => password, password, IsValid, "Invalid Password");
DateCreated = DateTime.Now;
}
static bool IsValid(string candidate)
{
//password cannot contain be whitespace
if (string.IsNullOrWhiteSpace(candidate))
return false;
const string passwordPattern = #"^(?=.*[A-Z].*[A-Z])(?=.*[!##$&=()-*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{20}$";
var match = Regex.Match(candidate, passwordPattern);
return match.Success;
}
public DateTime DateCreated { get; private set; }
public int DaysPasswordValid
{
get { return _daysPasswordValid; }
set
{
const int minimunDays = 0;
const int maximumDays = 90;
if (value <= maximumDays && value > minimunDays)
_daysPasswordValid = value;
else
throw new ArgumentOutOfRangeException(
"Password must be valid more than {0} and no more than {1} days.".Fmt(minimunDays, maximumDays));
}
}
public static implicit operator string(Password password)
{
return password.Value;
}
public static explicit operator Password(string value)
{
return new Password(value);
}
}
I would like to be able to create a fixture based on the Password class and have the fixture created with a valid password, in other words, a password that matches the RegEx pattern in the Password class. I have been looking at the RegularExpressionGenerator available in AutoFixture but haven't quite gotten things to work. Here is the builder have so far:
public class ValidPasswordBuilder : ISpecimenBuilder
{
public ValidPasswordBuilder(string regularExpressionRequest)
{
PasswordRegularExpression = regularExpressionRequest;
}
public string PasswordRegularExpression { get; private set; }
public object Create(object request, ISpecimenContext context)
{
var pi = request as ParameterInfo;
if (pi != null && pi.Name == "password" && pi.ParameterType == typeof(string))
{
var generator = new RegularExpressionGenerator();
var regExRequest = new RegularExpressionRequest(PasswordRegularExpression);
var result = generator.Create(regExRequest, context);
return result.ToString();
}
return new NoSpecimen(request);
}
}
Here is the test:
[Fact]
public void ValidPasswordMatches()
{
var fixture = new Fixture();
fixture.Customizations.Add(new ValidPasswordBuilder(PasswordPattern));
Action a = () => fixture.Create<Password>();
a.ShouldNotThrow<ArgumentException>();
}
I can run the test as setup above, and it passes, but if I debug it, I get an error in the IsValid function in the Password class (through the Guard clause) that says that the password returned from the builder is:
Ploeh.AutoFixture.Kernel.NoSpecimen
I never seem to get a result that matches the RegEx pattern. I feel like I'm close, but need some help getting over the hump.
Thanks!
As it looks like, the pattern you use is not supported:
^(?=.*[A-Z].*[A-Z])(?=.*[!##$&=()-*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{20}$
Try with a different Regular Expression.
Edit: Or try doing this or this, in order to configure AutoFixture to use a different Regular Expression, without changing the Password class.
AutoFixture turns Regular Expressions into Automatons by applying the algorithms of dk.brics.automaton.
You may use a different pattern or use a different engine to reverse the Regular Expression into an Automaton. As an example, you can use the Rex engine.
Though, even with Rex your Regular Expression is not supported, as the following constructs are currently not supported by Rex:
anchors \G, \b, \B, named groups, lookahead, lookbehind, as-few-times-as-possible quantifiers, backreferences, conditional alternation, substitution.
If you want to try Rex with AutoFixture you can use the following generator:
internal class RexRegularExpressionGenerator : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (request == null)
return new NoSpecimen();
var regularExpressionRequest = request as RegularExpressionRequest;
if (regularExpressionRequest == null)
return new NoSpecimen();
var pattern = regularExpressionRequest.Pattern;
try
{
var regex = RexEngine
.GenerateMembers(
new RexSettings(pattern) { k = 1 })
.FirstOrDefault();
if (Regex.IsMatch(regex, pattern))
return regex;
}
catch (ArgumentException)
{
return new NoSpecimen(request);
}
return new NoSpecimen(request);
}
}
As far as I can tell, you can download Rex only as a .NET application (.exe) file which you can then reference like any other managed assembly in your project.
In my class, I have a property for a file attachment like so...
public class Certificate {
[Required]
// TODO: Wow looks like there's a problem with using regex in MVC 4, this does not work!
[RegularExpression(#"^.*\.(xlsx|xls|XLSX|XLS)$", ErrorMessage = "Only Excel files (*.xls, *.xlsx) files are accepted")]
public string AttachmentTrace { get; set; }
}
I don't see anything wrong with my regex, but I always get ModelState.IsValid false. This seems pretty trivial and simple regex, am I missing something? Do I need to write my own custom validation?
I'm populating AttachmentTrace via a regular input of type file:
<div class="editor-label">
#Html.LabelFor(model => model.AttachmentTrace)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.AttachmentTrace, new { type = "file" })
#Html.ValidationMessageFor(model => model.AttachmentTrace)
</div>
The action method is just a regular action:
public ActionResult Create(Certificate certificate, HttpPostedFileBase attachmentTrace, HttpPostedFileBase attachmentEmail)
{
if (ModelState.IsValid)
{
// code ...
}
return View(certificate);
}
Ok, here's the solution I found. I'm sure there are other solutions out there. First a little background, because my application uses EF code-first migration, specifying a HttpPostedFileBase property type in my model, produces this error when adding migration:
One or more validation errors were detected during model generation:
System.Data.Entity.Edm.EdmEntityType: : EntityType
'HttpPostedFileBase' has no key defined. Define the key for this
EntityType. \tSystem.Data.Entity.Edm.EdmEntitySet: EntityType:
EntitySet 'HttpPostedFileBases' is based on type 'HttpPostedFileBase'
that has no keys defined.
So I really had to stick with using a string type for the AttachmentTrace property.
The solution is to employ a ViewModel class like this:
public class CertificateViewModel {
// .. other properties
[Required]
[FileTypes("xls,xlsx")]
public HttpPostedFileBase AttachmentTrace { get; set; }
}
Then create a FileTypesAttribute like so, I borrowed this code from this excellent post.
public class FileTypesAttribute : ValidationAttribute {
private readonly List<string> _types;
public FileTypesAttribute(string types) {
_types = types.Split(',').ToList();
}
public override bool IsValid(object value) {
if (value == null) return true;
var postedFile = value as HttpPostedFileBase;
var fileExt = System.IO.Path.GetExtension(postedFile.FileName).Substring(1);
return _types.Contains(fileExt, StringComparer.OrdinalIgnoreCase);
}
public override string FormatErrorMessage(string name) {
return string.Format("Invalid file type. Only {0} are supported.", String.Join(", ", _types));
}
}
In the controller Action, I needed to make a change to use the ViewModel instead, then map it back to my Entity using AutoMapper (which is excellent by the way):
public ActionResult Create(CertificateViewModel certificate, HttpPostedFileBase attachmentTrace, HttpPostedFileBase attachmentEmail) {
if (ModelState.IsValid) {
// Let's use AutoMapper to map the ViewModel back to our Certificate Entity
// We also need to create a converter for type HttpPostedFileBase -> string
Mapper.CreateMap<HttpPostedFileBase, string>().ConvertUsing(new HttpPostedFileBaseTypeConverter());
Mapper.CreateMap<CreateCertificateViewModel, Certificate>();
Certificate myCert = Mapper.Map<CreateCertificateViewModel, Certificate>(certificate);
// other code ...
}
return View(myCert);
}
For the AutoMapper, I created my own TypeConverter for the HttpPostedFileBase as follows:
public class HttpPostedFileBaseTypeConverter : ITypeConverter<HttpPostedFileBase, string> {
public string Convert(ResolutionContext context) {
var fileBase = context.SourceValue as HttpPostedFileBase;
if (fileBase != null) {
return fileBase.FileName;
}
return null;
}
}
That's it. Hope this helps out others who may have this same issue.
I have to check some textField with the following regex:
[\sa-zA-Z.'-àáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+
It works with regex checkers but it doesn't work with my GWT/GXT application. I use the function above in a class that extends AbstractValidator.
public static native boolean isValidName(String name) /*-{
var pattern = /[\sa-zA-Z.\'-àáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+/;
return pattern.test(name);
}-*/;
I use GXT2 and GWT 1.6.4.
have you tried using String.macthes for validate the value and Validator class in gxt TextField?
someTextField.setValidator(new Validator() {
#Override
public String validate(Field<?> field, String value) {
return value.matches("[\\sa-zA-Z.'-àáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+")
? null : "not a valid value";
}
});
Why go native, while you can still use Java ? Or even better, try to see if GXT gives you some validation tools. Like Validators
Related : Regular Expressions and GWT
OK for gxt2...
the corresponding method is setRegex(String regex) which will get called if all other validators have passed
http://www.jarvana.com/jarvana/view/com/extjs/gxt/2.2.0/gxt-2.2.0-javadoc.jar!/com/extjs/gxt/ui/client/widget/form/TextField.html
Why don't you use (for gxt3):
com.sencha.gxt.widget.core.client.form.Field<T>.addValidator(Validator<T> validator)
field.addValidator(new RegExValidator( "[\sa-zA-Z.\'-àáâãäåçèéêëìíîïðòóôõöùúûüýÿ]", "some message"));
see gxt field api
see gxt RegExValidator
Sencha GXT4:
enum VType
public enum VType {
ALPHABET("^[a-zA-Z_]+$", "Alphabet"), ALPHANUMERIC("^[a-zA-Z0-9_]+$",
"Alphanumeric"), NUMERIC("^[+0-9]+$", "Numeric"), EMAIL("^(\\w+)([-+.][\\w]+)*#(\\w[-\\w]*\\.){1,5}([A-Za-z]){2,4}$","Email");
String regex;
String name;
VType(String regex, String name) {
this.regex = regex;
this.name = name;
}
}
Validator class
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.EditorError;
import com.sencha.gxt.widget.core.client.form.Validator;
import com.sencha.gxt.widget.core.client.form.error.DefaultEditorError;
public class VTypeValidator implements Validator<String> {
private String message;
private final VType type;
public VTypeValidator(VType type,String message){
this.type = type;
this.message=message;
}
#Override
public List<EditorError> validate(Editor<String> editor, String value) {
List<EditorError> res = null;
if (!value.matches(type.regex)) {
List<EditorError> errors = new ArrayList<EditorError>();
errors.add(new DefaultEditorError(editor, message,""));
return errors;
}
return res;
}
}
How to use with textField
field.addValidator(new VTypeValidator(VType.EMAIL,"Invalid email"));
I'm Using EmailValidator for Validation:
<mx:EmailValidator id="Email_Validator"
source="{txtEmail}"
property="text" required="false"/>
And My Code is:
var isValidForm:Boolean=true;
var validatorArr:Array = new Array();
validatorArr.push(Email_Validator);
var validatorErrorArray:Array = Validator.validateAll(validatorArr);
isValidForm = validatorErrorArray.length == 0;
if(isValidForm)
{
//.....
}
It is working fine. But I want domain should be "gmail.com" if some other, validation should return false.. How can I achive this?
I think Regular Expressions are usefull.. But I dont Know to use the same in flex?...
If all you are testing for is "gmail.com", you don't need to use regular expressions at all. A simple
if (txtEmail.text.indexOf ("gmail.com") < 0) doStuff();
// index < 0 => address does not contain search string
would be enough.
Nonetheless, ActionScript 3 has the RegExp class to provide regular expression functionality. See this tutorial.
Use a component
checkout this
public class TextInputEmail extends TextInput
{
private var emailValidator:EmailValidator = new EmailValidator();
private var validator:ValidationResultEvent;
public function TextInputEmail()
{
super();
this.emailValidator.source = this;
this.emailValidator.property = "text";
this.addEventListener("enter", this.validate);
}
private function validate(event:Event):void
{
validator = emailValidator.validate();
if (validator.type == ValidationResultEvent.VALID)
{
this.errorString = "";
} else {
this.errorString = validator.message;
}
}
}
error strings are in build in Package.
I hope this helps you better...:-)