Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
badhitman committed Aug 28, 2019
1 parent 9a932bd commit 0100b5a
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 0 deletions.
11 changes: 11 additions & 0 deletions AspDotNetCore2BinderFloatingDecimalModel.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
</ItemGroup>

</Project>
33 changes: 33 additions & 0 deletions CustomDoubleModelBinderProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
////////////////////////////////////////////////
// © https://github.com/badhitman - @fakegov
////////////////////////////////////////////////
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.Extensions.Logging;

namespace AspDotNetCore2BinderFloatingDecimalModel
{
public class CustomDecimalModelBinderProvider : IModelBinderProvider
{
private IModelBinder binder;

public IModelBinder GetBinder(ModelBinderProviderContext context)
{
ILoggerFactory logger = context.Services.GetService(typeof(ILoggerFactory)) as ILoggerFactory;

if (context.Metadata.ModelType == typeof(double))
binder = new CustomFloatingModelBinder(new SimpleTypeModelBinder(typeof(double), logger));

else if (context.Metadata.ModelType == typeof(float))
binder = new CustomFloatingModelBinder(new SimpleTypeModelBinder(typeof(float), logger));

else if (context.Metadata.ModelType == typeof(decimal))
binder = new CustomFloatingModelBinder(new SimpleTypeModelBinder(typeof(decimal), logger));

else
return null;

return binder;
}
}
}
104 changes: 104 additions & 0 deletions CustomFloatingModelBinder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
////////////////////////////////////////////////
// © https://github.com/badhitman - @fakegov
////////////////////////////////////////////////
using Microsoft.AspNetCore.Mvc.ModelBinding;
using System;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace AspDotNetCore2BinderFloatingDecimalModel
{
public class CustomFloatingModelBinder : IModelBinder
{
private readonly IModelBinder FallbackModelBinder;
private string FieldName;
private string FieldValueAsString;
private string FieldValueAsNormalString;
private ValueProviderResult PartValues;

protected readonly Regex FloatPattern = new Regex(@"^(-?)[0-9]*(?:[.,][0-9]*)?$", RegexOptions.Compiled);
protected readonly Regex FloatSeparator = new Regex(@"[.,]", RegexOptions.Compiled);

public CustomFloatingModelBinder(IModelBinder fallback_model_binder)
{
this.FallbackModelBinder = fallback_model_binder;
}

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

FieldName = model_binding_context.FieldName;

PartValues = model_binding_context.ValueProvider.GetValue(FieldName);

if (PartValues == ValueProviderResult.None)
return FallbackModelBinder.BindModelAsync(model_binding_context);

FieldValueAsString = FieldValueAsNormalString = PartValues.FirstValue;

////////////////////////////////////////////////////
// если строка содержит десятичный/дробный разделитель -> строка дополняется нулями с обоих сторон.
// Таким образом исключаем точки в начале или в конце строки:
// ".5" -> "0.50"
// "5." -> "05.0"
if (FloatSeparator.IsMatch(FieldValueAsNormalString))
FieldValueAsNormalString = "0" + FieldValueAsNormalString + "0";

////////////////////////////////////////////////////
// заменим дробный разделитель на текущий системный
FieldValueAsNormalString = FloatSeparator.Replace(FieldValueAsNormalString, CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);

////////////////////////////////////////////////////
// если не корректная строка -> передаём привязку системному привязчику
if (!FloatPattern.IsMatch(FieldValueAsNormalString))
return FallbackModelBinder.BindModelAsync(model_binding_context);

if (model_binding_context.ModelMetadata.ModelType == typeof(double))
model_binding_context.Result = ModelBindingResult.Success(GetDoubleFromString);
else if (model_binding_context.ModelMetadata.ModelType == typeof(float))
model_binding_context.Result = ModelBindingResult.Success(GetFloatFromString);
else if (model_binding_context.ModelMetadata.ModelType == typeof(decimal))
model_binding_context.Result = ModelBindingResult.Success(GetDecimalFromString);
else
return FallbackModelBinder.BindModelAsync(model_binding_context);

return Task.CompletedTask;
}

public double GetDoubleFromString
{
get
{
if (!double.TryParse(FieldValueAsNormalString, NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out double ret_val))
return 0;

return ret_val;
}
}

public decimal GetDecimalFromString
{
get
{
if (!decimal.TryParse(FieldValueAsNormalString, NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out decimal ret_val))
return 0;

return ret_val;
}
}

public float GetFloatFromString
{
get
{
if (!float.TryParse(FieldValueAsNormalString, NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out float ret_val))
return 0;

return ret_val;
}
}
}
}
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,16 @@
# ASP.NET Core 2.2 BinderFloatingDecimalModel
Привязчик модели для числовых значений double, float и decimal в ASP.NET Core 2.2

Использование:
```C#
using AspDotNetCore2BinderFloatingDecimalModel;
// ...
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddMvc(opts =>
{
opts.ModelBinderProviders.Insert(0, new CustomDecimalModelBinderProvider());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
```

0 comments on commit 0100b5a

Please sign in to comment.