131 lines
4.5 KiB
C#
131 lines
4.5 KiB
C#
using Microsoft.AspNetCore.Mvc.Abstractions;
|
|
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
|
using Microsoft.AspNetCore.Routing;
|
|
using Nop.Core.Http.Extensions;
|
|
|
|
namespace Nop.Web.Framework.Controllers;
|
|
|
|
/// <summary>
|
|
/// Attribute to validate whether a certain form name (or value) was submitted
|
|
/// </summary>
|
|
public sealed class FormValueRequiredAttribute : ActionMethodSelectorAttribute
|
|
{
|
|
private readonly string[] _submitButtonNames;
|
|
private readonly FormValueRequirement _requirement;
|
|
private readonly bool _validateNameOnly;
|
|
|
|
/// <summary>
|
|
/// Ctor
|
|
/// </summary>
|
|
/// <param name="submitButtonNames">Submit button names</param>
|
|
public FormValueRequiredAttribute(params string[] submitButtonNames) :
|
|
this(FormValueRequirement.Equal, submitButtonNames)
|
|
{
|
|
}
|
|
/// <summary>
|
|
/// Ctor
|
|
/// </summary>
|
|
/// <param name="requirement">Requirement</param>
|
|
/// <param name="submitButtonNames">Submit button names</param>
|
|
public FormValueRequiredAttribute(FormValueRequirement requirement, params string[] submitButtonNames) :
|
|
this(requirement, true, submitButtonNames)
|
|
{
|
|
}
|
|
/// <summary>
|
|
/// Ctor
|
|
/// </summary>
|
|
/// <param name="requirement">Requirement</param>
|
|
/// <param name="validateNameOnly">A value indicating whether we should check "name" attribute only (not "value")</param>
|
|
/// <param name="submitButtonNames">Submit button names</param>
|
|
public FormValueRequiredAttribute(FormValueRequirement requirement, bool validateNameOnly, params string[] submitButtonNames)
|
|
{
|
|
//at least one submit button should be found
|
|
_submitButtonNames = submitButtonNames;
|
|
_validateNameOnly = validateNameOnly;
|
|
_requirement = requirement;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Is valid?
|
|
/// </summary>
|
|
/// <param name="routeContext">Route context</param>
|
|
/// <param name="action">Action descriptor</param>
|
|
/// <returns>Result</returns>
|
|
public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
|
|
{
|
|
if (!routeContext.HttpContext.Request.IsPostRequest())
|
|
return false;
|
|
|
|
var form = routeContext.HttpContext.Request.ReadFormAsync().Result;
|
|
|
|
foreach (var buttonName in _submitButtonNames)
|
|
{
|
|
try
|
|
{
|
|
switch (_requirement)
|
|
{
|
|
case FormValueRequirement.Equal:
|
|
{
|
|
if (_validateNameOnly)
|
|
{
|
|
//"name" only
|
|
if (form.Keys.Any(x => x.Equals(buttonName, StringComparison.InvariantCultureIgnoreCase)))
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
//validate "value"
|
|
//do not iterate because "Invalid request" exception can be thrown
|
|
string value = form[buttonName];
|
|
if (!string.IsNullOrEmpty(value))
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
case FormValueRequirement.StartsWith:
|
|
{
|
|
if (_validateNameOnly)
|
|
{
|
|
//"name" only
|
|
if (form.Keys.Any(x => x.StartsWith(buttonName, StringComparison.InvariantCultureIgnoreCase)))
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
//validate "value"
|
|
foreach (var formValue in form.Keys)
|
|
if (formValue.StartsWith(buttonName, StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
var value = form[formValue];
|
|
if (!string.IsNullOrEmpty(value))
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
//try-catch to ensure that no exception is throw
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Requirement
|
|
/// </summary>
|
|
public enum FormValueRequirement
|
|
{
|
|
/// <summary>
|
|
/// Equal
|
|
/// </summary>
|
|
Equal,
|
|
/// <summary>
|
|
/// Starts with
|
|
/// </summary>
|
|
StartsWith
|
|
} |