-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
162 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
``` |