Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// Provides validation logic for Delta<TEntity> paremeters for PATCH & MERGE actions.
- module WebApi.Infrastructure.Validation.DeltaOfTEntityTypeValidationProvider
- open ImpromptuInterface.FSharp
- open System
- open System.Net.Http
- open System.Web.Http
- open System.Web.Http.Controllers
- open System.Web.Http.Metadata
- open System.Web.Http.OData
- open System.Web.Http.Validation
- let [<Literal>] PatchMethod = "PATCH"
- let [<Literal>] MergeMethod = "MERGE"
- /// Returns true if the given method is PATCH or MERGE.
- let isPatchOrMergeMethod (method' : HttpMethod) =
- [ PatchMethod; MergeMethod ] |> Seq.exists method'.Method.Equals
- /// Looks for an object of type Delta<TEntity> in the provided sequence.
- /// Returns None if the object could not be found.
- let tryFindDeltaParameter = Seq.tryFind (function
- | null -> false
- | arg -> let argType = arg.GetType ()
- argType.IsGenericType && typedefof<Delta<_>>.Equals (argType.GetGenericTypeDefinition ())
- )
- /// Creates an instance of the entity type the Delta<TEntity> object encapsulates.
- let createEntityInstance deltaParameter =
- deltaParameter?EntityType
- |> (Activator.CreateInstance : Type -> Object)
- /// Looks for validators that can validate the property represented by the passed metadata.
- let findPropertyValidators metadata = seq {
- let validatorProviders = GlobalConfiguration.Configuration.Services.GetModelValidatorProviders ()
- for validatorProvider in validatorProviders do
- yield! validatorProvider.GetValidators (metadata, validatorProviders)
- }
- /// Creates a ModelMetadata object representing the provided property of the entity object.
- let createMetadata entity propertyName =
- let property = entity.GetType().GetProperty propertyName
- ModelMetadata (
- provider = GlobalConfiguration.Configuration.Services.GetModelMetadataProvider (),
- containerType = property.DeclaringType,
- modelAccessor = Func<_> (fun () -> property.GetValue entity),
- modelType = property.PropertyType,
- propertyName = property.Name
- )
- /// Validates all changed properties of the provided Delta<TEntity> object and returns
- /// a sequence of validation results.
- let validateDelta deltaParameter = seq {
- let entity = createEntityInstance deltaParameter
- do deltaParameter?CopyChangedValues entity
- for propertyName in deltaParameter?GetChangedPropertyNames () do
- let metadata = createMetadata entity propertyName
- for propertyValidator in findPropertyValidators metadata do
- yield! propertyValidator.Validate (metadata, entity)
- }
- /// Adds the provided validation results to the action context as model errors.
- let addModelErrors (actionContext : HttpActionContext) =
- Seq.iter (fun (validationResult : ModelValidationResult) ->
- actionContext.ModelState.AddModelError (validationResult.MemberName, validationResult.Message)
- )
- /// Looks for a Delta<TEntity> object passed as an argument to the action method
- /// and validates it. The validation results are added as model errors to the model state.
- let searchAndValidateDelta (actionContext : HttpActionContext) =
- if isPatchOrMergeMethod actionContext.Request.Method then
- tryFindDeltaParameter actionContext.ActionArguments.Values
- |> Option.map validateDelta
- |> Option.iter (addModelErrors actionContext)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement