Giter Club home page Giter Club logo

jsonmodelbinder's People

Contributors

brunozell avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

jsonmodelbinder's Issues

Does the JsonModelBinder work with dot net core 2

Hi,

I saw the reference to this library at a StackOverflow question.

Does this library work with dot net core 2, as I always get null value for the parameter decorated with
the [ModelBinder(BinderType = typeof(JsonModelBinder))] controller action method.

I had created an empty project and then installed the library via Nuget.

model empty

Im trying with your solution but I have a problem. Model is always null. Only image file was read correctly. This is post request which is send from my video camera after license plate is recognized:

POST /alpv/receive.php HTTP/1.1\r\n Host: 10.13.24.13\r\n Content-Length: 7160\r\n Content-Type: multipart/form-data; boundary=------------------------3df4e8eee91da308\r\n --------------------------3df4e8eee91da308 Content-Disposition: form-data; name="event"; filename="20190204103017_10536event_7000175.json" Content-Type: application/octet-stream { "packetCounter":"7000175", "datetime":"20190204 103017000", "plateText":"\u004c\u0042\u0045\u0033\u0039\u0037", "plateCountry":"SWE", "plateConfidence":"0.716159", "carState":"new", "geotag":{"lat": 50.418114,"lon": 30.476213}, "imageType": "plate", "plateImageType": "png", "plateImageSize": "0", "carMoveDirection":"in", "timeProcessing":"0", "plateCoordinates":[1614, 880, 172, 28], "carID":"18", "GEOtarget":"Camera", "sensorProviderID":"defaultID" } --------------------------3df4e8eee91da308 Content-Disposition: form-data; name="image"; filename="20190204103016_999776lp_LBE397_7000175.png" Content-Type: application/octet-stream <IMAGE DATA> --------------------------3df4e8eee91da308--

There are two files: "image" and "event".

In controller I write this:

public IActionResult NewEvent([ModelBinder(BinderType = typeof(JsonModelBinder))] DataFromCameraModel @event, IFormFile image) { return Ok(); }

and DataFromCameraModel

public class DataFromCameraModel { public int packetCounter {get;set;} public string Datetime {get;set;} public string plateText {get;set;} }

Optional model validation

Please, make a model validation optional.
As it is a slow operation via Reflection + LINQ etc.
It would be great to have bool IsValidateModel property in the binding constructor.

Data Model Validation

Looks like the Model's don't participate in the Data Validation system, when we custom Model Bind.

I added some code so that Data Model Validation would work:

   public class JsonModelBinder : IModelBinder
    {
        private readonly MvcJsonOptions _options;

        public JsonModelBinder(IOptions<MvcJsonOptions> options) =>
            _options = options.Value;

        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }

            // Test if a value is received
            var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            if (valueProviderResult != ValueProviderResult.None)
            {
                bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);

                // Deserialize from string
                string serialized = valueProviderResult.FirstValue;

                // Use custom json options defined in startup if available
                object deserialized = _options?.SerializerSettings == null ?
                    JsonConvert.DeserializeObject(serialized, bindingContext.ModelType) :
                    JsonConvert.DeserializeObject(serialized, bindingContext.ModelType, _options.SerializerSettings);

                // DataAnnotation Validation. Validate Properties and Fields.
                var validationResultProps = from prop in TypeDescriptor.GetProperties(deserialized).Cast<PropertyDescriptor>()
                                       from attribute in prop.Attributes.OfType<ValidationAttribute>()
                                       where !attribute.IsValid(prop.GetValue(deserialized))
                                       select new { Propertie = prop.Name, ErrorMessage = attribute.FormatErrorMessage(string.Empty) };

                var validationResultFields = from field in TypeDescriptor.GetReflectionType(deserialized).GetFields().Cast<FieldInfo>()
                                       from attribute in field.GetCustomAttributes<ValidationAttribute>()
                                       where !attribute.IsValid(field.GetValue(deserialized))
                                       select new { Propertie = field.Name, ErrorMessage = attribute.FormatErrorMessage(string.Empty) };

                var errors = validationResultFields.Concat(validationResultFields);

                // Add the ValidationResult's to the ModelState
                foreach (var validationResultItem in errors)
                    bindingContext.ModelState.AddModelError(validationResultItem.Propertie, validationResultItem.ErrorMessage);

                // Set successful binding result
                bindingContext.Result = ModelBindingResult.Success(deserialized);
#if NET451
                return Task.FromResult(0);
#else
                return Task.CompletedTask;
#endif
            }
#if NET451
            return Task.FromResult(0);
#else
            return Task.CompletedTask;
#endif
        }
    }

I hacked this together from various internet posts. I wonder if there isn't an easier way to just ask the deserialzied object to validate itself?

For now, I iterate the Properties and Fields, and call the ValidationAttribute.IsValid against the data.

If one parameter is empty, returning 500

For example: 1 parameter acquired but value is empty, it turn unhanded exception and Controller not invoked.

If add in JsonModelBinder.cs: 43 fix below, Controller will be invoked and parameter == null as is.

// Add null check for parameter
if (string.IsNullOrEmpty(serialized))
{
bindingContext.Result = ModelBindingResult.Success(null);
return Task.CompletedTask;
}

Before fix:
image

System.ArgumentNullException: Value cannot be null. (Parameter 'instance') at System.ComponentModel.TypeDescriptor.GetReflectionType(Object instance) at BrunoZell.ModelBinding.JsonModelBinder.BindModelAsync(ModelBindingContext bindingContext) in C:\Users\b.yanish\source\repos\JsonModelBinder\src\JsonModelB inder\JsonModelBinder.cs:line 59 at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BinderTypeModelBinder.BindMo delAsync(ModelBindingContext bindingContext) at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(Actio nContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value) at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c_ _DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInn erFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, St ate next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourc eFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scop e scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceEx ecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipel ineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Sco pe scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Aw aited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTas k|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpCont ext context) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.Proces sRequests[TContext](IHttpApplication1 application)
`

After fix:
image

Code bug

First of all, thank you very much for this code.
I just wanted to let you know there is a bug in your code.

This line:
var errors = validationResultFields.Concat(validationResultFields);
should be
var errors = validationResultFields.Concat(validationResultProps);

Again, thank you!

Support `System.Text.Json` in ASP.NET Core 3.0 apps

.NET Core 3.0 introduces a new platform native Json deserializer. This is used by default by ASP.NET Core 3.0. This package, however, does imply you use Newtonsoft.Json and we blindly inject IOptions<MvcNewtonsoftJsonOptions>.

This is suboptimal as you cannot use this package with the new default Json deserializer and needs to be addressed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.