Symfony validator - validation

My question is related to symfony validator component. I don't use forms. And I want to move validation rules for each entity to separated class (like AuthorVlidator, BookingValidator etc.). How can I move it to separated classes and define rules?
Thanks.

Why would you like to move it to separated classes? With annotations it pretty easy to use it.
It's not a good idea to do it, but if you really want to do it in other classes, you could add this method in each classes that you want to validate:
class YourObject
{
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
YourObjectValidator::validate($this, $metadata);
}
}
And:
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\NotBlank;
class YourObjectValidator
{
public static function validate(YourObject $object, ClassMetadata $metadata)
{
$metadata->addPropertyConstraint('name', new NotBlank());
}
}
If you want separate this logic for add validation depending on properties value, it's not the proper way to do it. You should read the doc, callback could be a solution.

Related

Repeat Mutators

I'm using several mutators that are basically the same on different models and within the same models, for different fields. eg: to tidy dates:
public function getStartShortDateAttribute()
{
return $this->start_time->format('d-m-y');
}
Is there a standard way to reuse the same mutator for several fields across models?
Use a trait, which is a way to reuse code across classes.
trait HasStartTimes {
public function getStartShortDateAttribute()
{
return $this->start_time->format('d-m-y');
}
}
Now you can use this trait in your class, with the use statement. When done it will include the traits function, in the classes that uses the trait. This is an design approach that is used already in Laravel, see AuthenticatesUsers.
class YourModel {
use HasStartTimes;
}

Do you need a separate IValidationAttributeAdapterProvider for each custom attribute?

The code seems straightforward for an adapter provider, something like this:
public class KittensMustBeCuteAttributeAdapterProvider : IValidationAttributeAdapterProvider
{
private readonly IValidationAttributeAdapterProvider _baseProvider = new ValidationAttributeAdapterProvider();
public IAttributeAdapter GetAttributeAdapter(ValidationAttribute attribute, IStringLocalizer stringLocalizer)
{
if (attribute is KittensMustBeCuteAttribute)
{
return new KittensMustBeCuteAttributeAdapter(attribute as KittensMustBeCuteAttribute, stringLocalizer);
}
else
{
return _baseProvider.GetAttributeAdapter(attribute, stringLocalizer);
}
}
}
Looks to me like I could rename this adapter provider to be generic and use it for all of my custom attributes, as I have several (not just KittensMustBeCuteAttribute).
However I can't find anything indicating on whether or not this is OK or if you need one each. All of the examples I've seen have it named like I have, specific to the attribute.
Can I just re-use one AdapterProvider by expanding my if statement?
Seems I should have just kept going, it became apparent afterwards that the adapter provider is registered as a singleton to be resolved through DI, therefore you have to have a single one containing all your custom attributes.

Missing HttpParameterBinding and ParameterBindingAttribute

I'm investigating Web Api in ASP.NET vNext using the daily builds. In a web api 2x project, I use HttpParameterBinding and ParameterBindingAttribute in some situations (see http://bit.ly/1sxAxdk); however, I can't seem to find either in vNext. Do/will these classes exist? If not, what are my alternatives?
Edit (1-22-15):
I want to be able to serialize a complex JS object to a JSON string, put the JSON string in a hidden form field (say name="data"), submit the form, and then bind my parameter to that JSON object on the server. This will never be done by a human, but rather by a machine. I also want this very same mechanism to work if the JSON is sent directly in the request body instead of form data. I also need this to work for several different types of objects.
I've been able to accomplish this scenario in Web Api 2.2 in a few different ways, including a custom ModelBinder; however, I remember reading an MSFT blog post that suggested to use a ModelBinder for query string binding, formatters for request body, and HttpParameterBinding for more general scenarios. Is it okay to read the request body in a ModelBinder ASP.NET 5, or is there a better mechanism for that? If so, then case closed and I will port my ModelBinder with a few minor changes.
I'm not sure that IInputFormatter will work for me in this case either.
Here are two rough approaches
Approach 1:
A quick and dirty approach would be to start with a Dto model
public class Dto
{
public Serializable Result { get; set; }
public Serializable FromForm
{
get { return Result; }
set { Result = value; }
}
[FromBody]
public Serializable FromBody
{
get { return Result; }
set { Result = value; }
}
}
public class Serializable
{
}
And an action method
public IActionResult DoSomething(Dto dto)
{
// Do something with Dto.Result
}
Then write a custom model binder for Serializable, that just works with Request.Form this way you never actually read the body yourself, and Form only reads it if it of type Form.
The down side of this is that ApiExplorer will not provide correct details (but I think since this is none-standard you are going to be in trouble here anyways).
Approach 2
You can alternatively just use the code from BodyModelBinder and create a custom binder for Serializable type above, that first tries to get it from the Form, and if it fails tries to get it from the Body. The Dto class in that case is not necessary.
Here is some pseudo code
if (inputType is yourtype)
{
if (request.Form["yourkey"] != null)
{
Use Json.Net to deserialize your object type
}
else
{
fall back to BodyModelBinder code
}
}
With this approach you can make it generic, and ApiExplorer will say the way to bind the type is unknown/custom (we haven't decided on the term yet :) )
Note:
Instead of registering the model binder you can use the [ModelBinder(typeof(customBinder))] attribute to apply it sparingly.
Here is a link to the BodyModelBinder code.
There is a new [FromHeader] attribute that allows you to bind directly to http header values if that is what you need.
https://github.com/aspnet/Mvc/issues/1671
https://github.com/aspnet/Mvc/search?utf8=%E2%9C%93&q=fromheader

ASP.NET Web API IQueryable<T> challenge

I want to use the following pattern in my controllers:
api/{controller}/{id}/{collection}
Example: api/customers/123/addresses
But I want to return IQueryable Of T from the corresponding Get action. I want something like this (simplified):
public IQueryable<????> GetCollection(int id, string collection)
{
switch(collection)
{
case "addresses":
return _addresses.AsQueryable();
break;
case "orders":
return _orders.AsQueryable();
break;
default:
throw new Exception(NotSupported);
}
}
Can this be done?
What would be the recommended approach?
#SLacks is correct that you should return IQueryable<object> or IQueryable<someBaseType> if you can.
The error your getting is a function of the DataContract Serializer. So you have a few options.
Switch to an alternate xml serlializer that supports what you want.
Swtitch to a form of output that bypasses the serializer at issue (say JSON using JSON.net)
Teach the data contract serializer how to serialize your object using the
For the "teach" option, you can teach in two ways.
(A) leverage the [KnownType(typeof(...))] attribute. Here's a post on the KnownType attribute. It's for WCF but should get you started.
(B) use a data contract resolver. This post should get you started.
Expanding on what #Ebarr said, the easiest way to accomplish this is to update the various classes which you want to be able to return this way, and have them inherit from a common base class or interface.
Example:
[KnownType(typeof(Address))]
[KnownType(typeof(Order))]
public abstract class _BaseObject { }
public partial class Address : _BaseObject { }
public partial class Order : _BaseObject { }
Now you can have your controller method look like:
public IQueryable<_BaseObject> GetCollection(int id, string collection) {
switch(collection) {
case "addresses":
return _addresses.AsQueryable();
case "orders":
return _orders.AsQueryable();
default:
throw new NotSupportedException();
}
}
Note that the [KnownType] attribute is in System.Runtime.Serialization. You should also be aware that this method will result in exactly what you would expect with regards to JSON serialization - but XML serialization will generally result in tags which show your objects as the base class (because that's what you returned) rather than the sub-classes.
Just return the non-generic IQueryable.
Or IQueryable<object> via covariance.

MVC 3 passing entity as an Interface

I'm currently working on an MVC 3 project using Ninject as my DI, the business objects are stored in a separate assembly. I'm running into an issue with the controller parameters, when posting back for CRUD operations I'm getting the error "Cannot create an instance of an interface". I am aware that you can't create an instance of an interface, but it seems like the only way I can get around this is to use a custom model binder and pass the FormCollection through. This seems really messy and I want to keep as much type specific code out of the project as I can - hence interfaces everywhere and Ninject to DI the concretes. Not only does custom model binding seem messy - won't I also lose my DataAnnotations?
Some code to describe what I have:
public ActionResult Create()
{
// I'm thinking of using a factory pattern for this part
var objectToCreate = new ConcereteType();
return (objectToEdit);
}
[HttpPost]
public ActionResult Create(IRecord record)
{
// check model and pass to repository
if (ModelState.IsValue)
{
_repository.Create(record);
return View();
}
return View(record);
}
Has anyone run into this before? How did you get over it?
Thanks!
but it seems like the only way I can get around this is to use a custom model binder
A custom model binder is the correct way to go. And by the way you should use view models as action arguments, not domain models or interfaces.
Not only does custom model binding seem messy - won't I also lose my DataAnnotations?
I don't know why you think that a custom model binder would make things messy. For me it's a great way to separate mapping logic into a reusable class. And, no you will not lose DataAnnotations. They will work perfectly fine on the concrete instance that the custom model binder would return.
Data passed to controllers action are simply holders for values. There shouldn't be any logic in them so there is nothing to decouple from. You can use concrete types (e.g Record) instead of interface (IRecord)
I made the same simple mistake. Ninject injects parameters into your constructor, but you added parameters to the Index Controller action.
It should look like this:
public class HomeController : Controller
{
private IRecord _record;
public HomeController(IRecord record)
{
_record = record;
}
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application. " +
_record .HelloWorld();
return View();
}
}
Make sense?

Resources