Is it possible to extend Breeze Metadata received from the server? - breeze

Wondering if anyone knows of any way to extend or configure Breeze so that the server returns additional info in the entity metadata? I'd like to use this additional data to assist with validation.
Assume I have an entity model like so with some Data Annotations applied:
public class Person {
[RegularExpression(#"^$|^http\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?",
ErrorMessage="The Website address does not appear to be valid.")]
public string Website { get; set; }
[Required(ErrorMessage="The Name field is required."),
MaxLength(150, ErrorMessage = "The Name field cannot exceed 150 characters."),
MinLength(5, ErrorMessage = "The Name field must be at least 5 characters.")]
public string Name { get; set; }
//...
}
Right now, Breeze only hooks up a MaxLength and Required Validator based on the metadata it receives since this is all it supports out of the box. If Breeze could include in the metadata the info described in the Data Annotation Attributes on the server entity, I'm thinking it would then be possible for Breeze to automatically add additional stock validators to the client EntityType (e.g. for RegEx, Range, MinLength, etc... ). This would cover the majority of basic validation use cases. Or, it could also allow developers to inspect the metadata and pull out useful info like the regEx string which we could use to hook up our own custom RegEx validator.
Also, is there any way to have Breeze include the value of the ErrorMessage validation attribute property in the metadata and then have the breeze client use that instead of the default required and maxLength messageTemplates? This would mean you would only have to define the error message in one place on the server and wouldn't have to customize it for each entity.
I'm trying to avoid having to create and register a bunch of custom validators on the client for what seems like basic validations that could be handled by Breeze automatically.
Thanks,
Richard

It's a great question.
We haven't yet done a good job of documenting how the server serializes metadata but this should be coming "real soon now". However, if you take a look at the json coming over the wire you'll notice that validators are serialized simply by name. This name is then looked up among the registered validators ( or validator factories) on the client and then added to the client side metadata. So the idea would be to register you validator "implementation" on the client with a unique name, and then have the server reference this name when sending metadata down from the server.
Hopefully this will be clearer in a week or so once we have documented how to create your own server side metadata to send down to the client.

Hmmm, one year has passed. Any news on this topic? I fully agree with RWHepburn that defining all validation rules on the server-side and have it available in breeze on the client side would be a perfect thing. This is what data annotations in EF are for - making it easier!

Related

How to only return a subset of specific fields from Model in REST APIController using .NET MVC4

I am writing a Web API that clients can make requests to to return data in XML format. I am implementing this in .NET using Enterprise Foundation and MVC4.
I am struggling a bit with how to only return a subset of some fields from my Models in my Controllers.
For arguments sake, lets say I have a Product model that contains attributes "Id", "Name", "Price" and "Actual Cost" (I am using an example from http://www.asp.net/web-api/overview/creating-web-apis/using-web-api-with-entity-framework/using-web-api-with-entity-framework,-part-6)
I need to expose a Web API for clients to query a specific Product to get its name and price, but in this response I don't want to return the "Actual Cost" property (because this is our secret).
Now in the link I provide this is exactly the problem they are attempting to solve by the use of DTO's (they define a DTO called ProductDTO that contains only the subsets I want to return). I have implemented this solution and I am indeed now able to return only the fields I specify in the DTO.
The problem is that the naming used for the returned entity in XML is now ProductDTO rather than Product, i.e. the returned XML is
{"ProductDTO":[{"Id":1,"Name":"Tomato Soup","Price":1.39}, {"Id":3,"Name":"Yo yo","Price":6.99]}
rather than
{"Product":[{"Id":1,"Name":"Tomato Soup","Price":1.39}, {"Id":3,"Name":"Yo yo","Price":6.99]}
That means that all of our clients currently using our API and expects a "Product" to be returned will now get a "ProductDTO" returned, which means that they will have to make changes to their code and which is unacceptable. I need to provide them with a "Product" with only the relevant set of sub-fields as they are currently getting. How do I achieve this? I cannot simply "ignore" a data member as suggested in prevent property from being serialized in web api because I also have some API cases where I indeed DO need to return ALL the attributes and not only a subset.
Just some background: We have an existing API server interface that was written in Ruby on Rails and we are now moving this over to C# and .NET MVC4. We also have a bunch of client applications already interfacing to our existing, older, Ruby on Rails API Server and we don't want clients to make any changes to their code. We are simply moving our API server code over from Ruby on Rails to C#. In Ruby on Rails I was simply able to apply a filter to the XML Serializer when I need to only return a subset of attributes on certain calls.
If you want to continue down the DTO route that you have started, which IMHO is a good idea as it gives you control of what you export without polluting your internal classes with export specific stuff, you can add a DataContract attribute to your ProductDTO class.
[DataContract(Name="Product")]
public class ProductDTO
{
[DataMember]
public int Id {get;set;}
[DataMember]
public string Name {get;set;}
}
The default XML formatter used in Web API is the DataContractSerializer.
You can read more about this here
Suppose you have a class like
public class product
{
public string Name{get; set;}
..
}
and you don't want to appear it in the response you can just use [XMLIgnore] attribute
[XMLIgnore]
public string Name{get; set;}
hopes this helps.

Code first: does fluent api influence UI?

I'm reading a book written by Julie Lerman on Code First. According to the book, annotations and fluent api give the same result. Everything depends on the style of the developer.
I know that annotations allow both to configure how code first generate database objects and how MVC customize UI elements. Let's say I use [Required, MaxLength(50)]. The attribute will generate a NOT NULL, nvarchar (50) in the database. It also will validate the input for that field.
[Required, MaxLength(50)]
public string Name { get; set; }
What if I decide to use Fluent API to configure Code first. Am I still going to need annotations to influence UI elements or using fluent API is going to be enough?
EDIT
How about annotations, such as Display that serve only for UI purposes? Do they have equivalents? If not, Will I need to use annotaions?
[Display(Name = "Date of Birth")]
public DateTime BirthDate { get; set; }
Thanks for helping
Data Annotation is the simplest way of telling a class to enforce some validation rule. You can do the same thing with Fluent API as well. Some people like doing it by data annotations and some people like it by doing with fluent API
Reasons to like it with Data Annotations
1) Keep the validation info about my entity in one place along with the entity definition
Reasons to like it with Fluent API
1) Keep my entity clean. It will have only my property info. No validation info. Clean and simple POCO. I will write validation on the OnModelCreating method in my data context class.
You can not do all Fluent API things with Data Annotations way. the same way you don't have few Data Annotations attributes equivalant not present with Fluent API way ( Ex : HasMinLength) . HasMinLength is something we will for our Model validation which usually makes sense in the UI.
For the UI Model Validation, you can not use the Fluent API alone. Fluent API's major role is to look into the fluent configuration we writes and act when creating the Model(Database) from the entities. Remember we are overriding the OnModelCreating method to write our fluent API configuration. So for the UI Validation (of my ViewModel), I would use the DataAnnotation way and use fluent API if i want to define some thing related to my datamodel like Define a foreign key or Map this Entity to a Table with different name etc..
EDIT : As per the question edit,
You should make use of the Data Annotations in this case. If you are doing code first. You may remember that that entity is going to be your Database table ( of course you can tell EF to ignore /rename specific columns). In that case, I would keep my Entities clean and Create a ViewModel which i will use in my UI. I will add my DataAnnotations in my ViewModel to handle it. I may write some mapping code which maps data from ViewModel to Model and Model to ViewModel wherever necessary.
If your entity model classes are doubling as your viewmodel classes, AND you are using the default out of the box DataAnnotationsValidationProvider, then you would need the dataannotations attributes on the model properties to get validation.
However, you should not double your entity classes as viewmodel classes. Take for instance, a controller that needs to have a ReturnUrl property in its model. You wouldn't want this in your entity model / database. Because of differences like this between the View model and the Entity model, the 2 should really be separate (yet cohesive) layers in your application. You can make them cohesive using a library like AutoMapper.
This is one of the reasons I prefer the fluent API. If you stick to the fluent API, then you would never put any attributes on any entity model classes or properties. When it comes time to show, insert, or update data, you put the attributes on the viewmodel classes only.
Also, the [Required] attribute on an entity type performs validation during SaveChanges, whereas a [Required] attribute on a viewmodel performs validation during model binding.
According to Julie Lerman's book on DbContext, you do NOT need any additional annotations to your Fluent API configuration. The Name property will get validated by Validation API as if it had been configured with Data Annotations.
According to the same book, MaxLength and Required are the only validation attributes with fluent API conterparts.

How can I validate an email address using the same method used by the DataAnnotations attribute DataType.EmailAddress?

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.

Only allow registrations from specific email domains

I am developing a site that uses the built in account model / controller that comes with the new MVC site template. I want to be able to only allow people to register if they use one of two specific domains in their email address.
So for example they can register if they use #domain1.co.uk or #domain2.co.uk, but no other domains (for example Gmail, Yahoo etc) can be used.
If anyone could point me in the right direction that would be great.
If using the MVC3 default site, you'll have a /Models/AccountModels.cs file. You can add a regular expression there to cause client-side* and server-side validation.
public class RegisterModel
{
...
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
[RegularExpression(#"^[a-zA-Z0-9._%+-]+(#domain1\.co\.uk|#domain2\.co\.uk)$", ErrorMessage = "Registration limited to domain1 and domain2.")]
public string Email { get; set; }
...
}
You will need to work out the expression that works out best for your requirements.
*client-side validation assumes your view references the jquery.validate script and has Html.ValidationMessageFor(m => m.Email) and/or Html.ValidationSummary(), which it should by default.
What more do you need than:
if( email.Contains("#domain1.co.uk") || email.Contains("#domain2.co.uk") )
Register(email);
else
throw, return false, whatever()
When it comes time to do your validation, i.e. is the email field populated, use a regex to make sure it is in the domain. As for what the actual regex should be, there is a lot of discussion online about validating email addresses with them. It even comes down to what a valid email address should contain. I found this example online, but it likely by no means the best solution, as I am not a regex expert. I have tried it with a few examples but I'm sure you can come up with some that will pass when they shouldn't:
^\w+([-+.']\w+)*#mail.com$
Where mail.com is the domain you want to check against. If you have multiple domains, you can either extend the regex or do multiple checks replacing mail.com in the regex with whatever else you want to use.
BTW I found that regex on this forums.asp.net post which touches on an issue like yours.
Validate that on both the frontend (the reg form) and the backend.
Here I recommend jquery validation plugin for client side validation.

Is there any way to stop DataAnnotation validation after the first failure?

In my ViewModels I use several DataAnnotations to validate the form data, there are usually 2-3 annotations per field.
For example a field for an email address might look like this:
[Required(ErrorMessage = "Please enter an email address.")]
[Email(ErrorMessage = "That is not a valid email address.")] // Custom
public string Email { get; set; }
Now if someone were to submit the form, both errors would show up in the validation summary. Is there any easy way to specify an order to run the validation annotations so that if the Required validation fails, the Email validation doesn't run?
If this isn't possible, how is this usually handled? Should I create custom validators for any field that has more than a single annotation? Would that be a proper way to use annotations, where a single one handles multiple types of validation?
(I'm also aware I could probably combine the Required annotation into the custom Email one, but this is just an example).
In this specific case I would probably take the same approach that the ASP.NET WebForms validators take - simply have the EmailAttribute validator return true if the value is null or empty.
Think about it:
If the e-mail address is required, then there will also be a [Required] validator and a null/empty e-mail address will generate a validation error anyway;
If the e-mail address is optional, a null/empty value should be considered valid.
No need to solve the complex problem of intercepting validators when you can just design the individual validators to play nice together!
Ordering validation: No.
In this case you could simply remove the Required attribute because "" or " " will fail the email address validation.
And yes, AFAIK creating a custom validation attribute that combines both of them is probably your best bet.
The problem here is that the ordering on the attributes is completely arbitrary and decided at compile time. You actually can enforce simple ordering depending on the kind of validation runner you're using. If you are using something like xVal and a validation runner like the one mentioned here, you can add an orderby clause like this to force a specific kind of attribute to sort to the top:
orderby attribute.GetType() == typeof(T) ? 0 : 1
Just make a strongly-typed validation runner method, where T is derived from the ValidationAttribute class.

Resources