113 lines
4.3 KiB
C#
113 lines
4.3 KiB
C#
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
|
|
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
|
using Sarand.Net.Standard.Base.App;
|
|
using Sarand.Net.Standard.Base.Utils;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection.PortableExecutable;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
|
|
// Ignore obsolete warning on ComplexTypeModelBinder.
|
|
#pragma warning disable 0618
|
|
|
|
namespace Sarand.BusinessMgr.Net.Core.Web.Middleware
|
|
{
|
|
//=======================================================================
|
|
/// <summary>
|
|
/// Maps a browser request to a data object. Default class provides a base implementation of a model binder.
|
|
/// <para>- Overridden to trim whitespace from input values.</para>
|
|
/// </summary>
|
|
public class SbmModelBinder : ComplexTypeModelBinder
|
|
{
|
|
//-------------------------------------------------------------------
|
|
// Construction.
|
|
public SbmModelBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) :
|
|
base(propertyBinders, loggerFactory)
|
|
{
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>
|
|
/// Creates the model with one (or more) injected service parameters.
|
|
/// </summary>
|
|
protected override object CreateModel(ModelBindingContext bindingContext)
|
|
{
|
|
var services = bindingContext.HttpContext.RequestServices;
|
|
var modelType = bindingContext.ModelType;
|
|
var ctors = modelType.GetConstructors();
|
|
foreach (var ctor in ctors)
|
|
{
|
|
var paramTypes = ctor.GetParameters().Select(p => p.ParameterType).ToList();
|
|
var parameters = paramTypes.Select(p => services.GetService(p)).ToArray();
|
|
if (parameters.All(p => p != null))
|
|
{
|
|
var model = ctor.Invoke(parameters);
|
|
return model;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>
|
|
/// Intercept String properties and trim whitespace.
|
|
/// </summary>
|
|
protected override void SetProperty(ModelBindingContext bindingContext, string modelName, ModelMetadata propertyMetadata, ModelBindingResult result)
|
|
{
|
|
//if (SbmSystem.DebugMode) Logger.Debug($"{SysUtil.Fn} Form property " + modelName + ": '" + result.Model.ToString() + ".");
|
|
object originalValue = result.Model;
|
|
// Anything that looks like a password will be left as is.
|
|
bool password = modelName.ContainsCI("Password");
|
|
// Exclude properties that retain leading/trailing whitespace.
|
|
if (result.Model is string)
|
|
{
|
|
if (!password)
|
|
{
|
|
string value = result.Model as string;
|
|
|
|
// Trim leading and trailing whitespace.
|
|
value = StringUtil.TrimAll(value);
|
|
|
|
// Check for multi-line.
|
|
if (value.Contains('\n'))
|
|
{
|
|
// Simplify line delimiters.
|
|
value = Regex.Replace(value, "\\r\\n", "\n");
|
|
// Remove white space in front of newlines.
|
|
value = Regex.Replace(value, "\\s+\\n", "\n");
|
|
// Remove multiple newlines.
|
|
value = Regex.Replace(value, "\\n+", "\n");
|
|
}
|
|
|
|
// Email addresses must be lowercase to ensure match to encrypted data.
|
|
if (modelName.EqualsCI("EmailAddress") || modelName.EqualsCI("AccountEmailAddress"))
|
|
value = value.ToLowerInvariant();
|
|
|
|
// Uppercase selected values.
|
|
if (modelName.EqualsCI("Postcode") || modelName.EqualsCI("AccountPostcode") || modelName.EqualsCI("RegisteredAddressPostcode"))
|
|
value = value.ToUpper();
|
|
|
|
// Assign resulting value.
|
|
result = ModelBindingResult.Success(value);
|
|
}
|
|
}
|
|
// Log property details.
|
|
if (result.Model != null && SbmSystem.DebugMode &&
|
|
// Ignore passwords.
|
|
!password &&
|
|
// Ignore items that correspond with objects in the model rather than values.
|
|
!result.Model.ToString().Equals(result.Model.GetType().FullName) &&
|
|
// Ignore form files.
|
|
!result.Model.ToString().ContainsCI("Microsoft.AspNetCore.Http.IFormFile"))
|
|
SaLogger.Debug(SysUtil.Fn + " Form property " + modelName + ": '" + result.Model.ToString() + "'." + (originalValue != null && !originalValue.Equals(result.Model) ? " Original value: '" + originalValue.ToString() + "'" : ""));
|
|
base.SetProperty(bindingContext, modelName, propertyMetadata, result);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
//=======================================================================
|
|
}
|