Array size validation in C# - c#

I have a controller method with array of integers input, which must not be null or more than 10 elements size. To validate input I 've made a class:
public class TestForm
{
[Required]
[MaxLength(10)]
public long[] feedIds { get; set; }
}
And controller method:
[HttpPost]
public async Task<IActionResult> DoSomeJob(TestForm form)
{
//Do some job
}
According to MSDN, System.ComponentModel.DataAnnotations.MaxLength can be used for array, but there is no validation, it gets null and array of any size. What am I doing wrong?

Here is what we use in one of our projects:
public class LengthAttribute : ValidationAttribute {
readonly int length;
public LengthAttribute(int length) {
this.length = length;
}
public override bool IsValid(object value) {
if (value is ICollection == false) { return false; }
return ((ICollection)value).Count == length;
}
}
On a property like the following:
public class CreateUserApiRequest : ApiRequest {
[DataMember]
[Length(128)]
[Description("クライアントキー")]
public byte[] clientKey { get; set; }
....

The MaxLength atribute works fine. The problem was in action filter. Here is the code:
services.AddMvc(options =>
{
options.Filters.Add(new MyValidationFilterAttribute());
//Some other code
}
public class MyValidationFilterAttribute: IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
if (context.ModelState.IsValid)
return;
if (!RequestRecognizingUtils.IsMobileAppRequest(context.HttpContext.Request))
return; //Here all validation results are ignored
}
}
In OnActionExecuting method validation errors were ignored

Related

.NET - It is possible to use DI with the State Pattern?

I'm studying design patterns in .NET and currently i'm trying to implement the State Pattern. But today i got to a problem and i can't figure out how to fix this situation.
I have some state classes, all of them implementing the state interface. One of the last states should connect to a data base, through a service injected by the .NET API Startup class, to persist the data and finish up the process.
The problem is... because of the dependency injection that i need to be in the final state, i can't instanciate this state object to progress to this point. I don't know how to continue from there. I don't know if i'm using the pattern wrong or if the use of dependency injection in this pattern is the problem. I can't give all the details of the problem because my studie's project is a little big mess at this moment, so i made a quick mimic of the structure i'm trying to build in my application.
States interface and the OperatingClass who will execute the state behaviour:
public interface IOperationState
{
public int ExecuteOperation(OperatingClass operatingClass);
}
public class OperatingClass
{
public IOperationState OperationState { get; set; }
public int id { get; set; }
public double value { get; set; }
public OperatingClass(int id) //constructor
{
this.id = id;
value = 0;
OperationState = new StartingState();
}
public int Execute()
{
return OperationState.ExecuteOperation(this);
}
}
Main Service: is the service who my controller calls after receive the API Post Method:
public class MainService
{
public int ExecuteFullOperation(int id)
{
//Receives an id and execute the state transition till the end;
var operatingClass = new OperatingClass(id);
return operatingClass.Execute();
}
}
The classes who represents the states and do the respective actions:
public class StartingState : IOperationState
{
public int ExecuteOperation(OperatingClass operatingClass)
{
// Do something...
operatingClass.OperationState = new MiddleState();
return operatingClass.Execute();
}
}
public class MiddleState : IOperationState
{
public int ExecuteOperation(OperatingClass operatingClass)
{
//Do something with the value... let's supose the result is 123, but it does not matter rn;
operatingClass.value = 123;
//Here is the problem: FinalState needs the PersistenceService, who
//receives a injected class to acess the database;
operatingClass.OperationState = new FinalState();
//I want to execute it and return the sucess or failure of the persistence.
return operatingClass.Execute();
}
}
public class FinalState : IOperationState
{
private readonly IPersistenceService PersistenceService;
public FinalState(IPersistenceService persistenceService)
{
PersistenceService = persistenceService;
}
public int ExecuteOperation(OperatingClass operatingClass)
{
return PersistenceService.PersistData(operatingClass.id, operatingClass.value) ? 200 : 503;
}
}
Additional info: i made the PersistenceService be injected in the Startup.cs as a Transient (i dont know how to make it in another way at this moment).
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IPersistenceService, PersistenceService>();
// Irrelevant configurations for the question.
services.AddControllers();
}
Please, help me if you can. I'm having a hard time trying to figure it out by myself.
Thank you for your patience and for your time reading it.
Firstly, we need some simple factory which will supply all necessary dependencies by their type. So let's create types for states:
public enum StateType
{
Start,
Middle,
Final
}
And simple factory:
public class StateFactory
{
private Dictionary<StateType, IOperationState> _stateByType;
// you can inject these dependencies through DI like that:
// public StateFactory(StartingState startingState,
// MiddleState middleState, FinalState finalState,
// PersistenceService persistenceService)
public StateFactory()
{
_stateByType = new Dictionary<StateType, IOperationState>()
{
{ StateType.Start, new StartingState(this) },
{ StateType.Middle, new MiddleState(this) },
{ StateType.Final, new FinalState(new PersistenceService()) }
};
}
public IOperationState GetByType(StateType stateType) =>
_stateByType[stateType];
}
Then we should register all our dependencies:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IPersistenceService, PersistenceService>();
services.AddTransient<StartingState>();
services.AddTransient<MiddleState>();
services.AddTransient<FinalState>();
services.AddTransient<MainService>();
services.AddTransient<OperatingClass>();
services.AddTransient<PersistenceService>();
services.AddTransient<StateFactory>();
}
Our states would look like this:
public class StartingState : IOperationState
{
private StateFactory _factory;
public StartingState(StateFactory stateFactory)
{
_factory = stateFactory;
}
public int ExecuteOperation(OperatingClass operatingClass)
{
// Do something...
// operatingClass.OperationState = new MiddleState();
operatingClass.OperationState = _factory.GetByType(StateType.Middle);
return operatingClass.Execute();
}
}
And MiddleState would look like this:
public class MiddleState : IOperationState
{
private StateFactory _factory;
public MiddleState(StateFactory stateFactory)
{
_factory = stateFactory;
}
public int ExecuteOperation(OperatingClass operatingClass)
{
//Do something with the value... let's supose the result is 123,
// but it does not matter rn;
operatingClass.value = 123;
//Here is the problem: FinalState needs the PersistenceService, who
//receives a injected class to acess the database;
operatingClass.OperationState = _factory.GetByType(StateType.Final);
//I want to execute it and return the sucess or failure of the persistence.
return operatingClass.Execute();
}
}
And Final state should look like this:
public class FinalState : IOperationState
{
private readonly IPersistenceService _persistenceService;
public FinalState(IPersistenceService persistenceService)
{
_persistenceService = persistenceService;
}
public int ExecuteOperation(OperatingClass operatingClass)
{
return _persistenceService
.PersistData(operatingClass.id, operatingClass.value)
? 200
: 503;
}
}
And other classes sush as OperatingClass would use StateFactory too:
public class OperatingClass
{
public IOperationState OperationState { get; set; }
public int id { get; set; }
public double value { get; set; }
public OperatingClass(int id, StateFactory stateFactory) //constructor
{
this.id = id;
value = 0;
// OperationState = new StartingState();
OperationState = stateFactory.GetByType(StateType.Start);
}
public int Execute()
{
return OperationState.ExecuteOperation(this);
}
}
And it is necessary to create concrete example of PersistenceService:
public interface IPersistenceService
{
bool PersistData(int id, double value);
}
public class PersistenceService : IPersistenceService
{
public bool PersistData(int id, double value)
{
throw new NotImplementedException();
}
}

Auto API Validation with FluentValidation

I want to auto apply validation for some models on requests execution. E.g. if I have a fluent validator for model A it will apply, if I don't have validator for model B then nothing happens. I wrote code, but maybe somebody can advise a better solution.
Create base class and interface:
public interface IBaseValidationModel
{
public void Validate(object validator, IBaseValidationModel modelObj);
}
public abstract class BaseValidationModel<T> : IBaseValidationModel
{
public void Validate(object validator, IBaseValidationModel modelObj)
{
var instance = (IValidator<T>)validator;
var result = instance.Validate((T)modelObj);
if (!result.IsValid && result.Errors.Any())
{
throw new Exception("INVALID");
}
}
}
Create model and validator:
public class LogInModel : BaseValidationModel<LogInModel>
{
public string? Name { get; set; }
public string? Password { get; set; }
public string? Domain { get; set; }
}
public class LogInModelValidator : AbstractValidator<LogInModel>
{
public LogInModelValidator()
{
RuleLevelCascadeMode = CascadeMode.Stop;
RuleFor(x => x.Domain).NotNull().NotEmpty();
RuleFor(x => x.Name).NotNull().NotEmpty();
RuleFor(x => x.Password).NotNull().NotEmpty();
}
}
Create action filter attribute to apply it to controllers:
public class ModelValidatorAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
foreach (var actionArgument in context.ActionArguments)
{
//validate that model is having validator and resolve it
if (actionArgument.Value is IBaseValidationModel model)
{
var modelType = actionArgument.Value.GetType();
var genericType = typeof(IValidator<>).MakeGenericType(modelType);
var validator = context.HttpContext.RequestServices.GetService(genericType);
if (validator != null)
{
// execute validator to validate model
model.Validate(validator, model);
}
}
}
base.OnActionExecuting(context);
}
}
Controller:
[Route("account")]
[ModelValidator]
public class AccountController : ControllerBase
{
public IActionResult Post([FromBody]LogInModel model)
{
return Ok("ok);
}
}

pass value returned from a method to action filter

I have _serviceOne injected into my controller that has a method which returns an int value. I'm trying to pass this value into my custom action filter.
This isn't working and I am getting the error: An object reference is required for the non-static field, method, or property 'NameController._serviceOne' where I try to set the Number = _serviceOne.GetIntNumber.
I am aware that I can access a value if it is inside the controller (eg: controller parameter, ViewBag, ViewData, a variable in the controller), but I want to pass the value to the CustomActionFilter filter's Number property.
The filter and service method work the way I want it to, but it won't let me pass the value from _serviceOne.GetIntNumber into the filter. Why is this not working, and how could I make it work?
NameController.cs:
public class NameController : Controller
{
private readonly ServiceOne _serviceOne;
public NameController(ServiceOne serviceOne)
{
_serviceOne = serviceOne;
}
[CustomActionFilter(Name = "CorrectName", Number = _serviceOne.GetIntNumber)] //does not work
[HttpGet]
public IActionResult Index()
{
return View();
}
}
CustomActionFilter.cs:
public class CustomActionFilter : ActionFilterAttribute
{
public string Name { get; set; }
public int Number { get; set; }
public override void OnActionExecuted(ActionExecutedContext context)
{
if (Name == "CorrectName" && Number == 1) {
RouteValueDictionary routeDictionary = new RouteValueDictionary { { "action", "SomeAction" }, { "controller", "NameController" } };
context.Result = new RedirectToRouteResult(routeDictionary);
}
base.OnActionExecuted(context);
}
}
Attributes are created at compile time so it's not possible to pass them run-time values in the constructor.
Instead, you can access NameController's instance of the service, like this:
public class NameController : Controller
{
private readonly ServiceOne _serviceOne;
public ServiceOne ServiceOne => _serviceOne;
public NameController(ServiceOne serviceOne)
{
_serviceOne = serviceOne;
}
}
public class CustomActionFilter : ActionFilterAttribute
{
public string Name { get; set; }
public int Number { get; set; }
public override void OnActionExecuted(ActionExecutedContext context)
{
var controller = context.Controller as NameController;
var service = controller.ServiceOne;
//Use the service here
}
}
See also Access a controller's property from an action filter

How to pass a parameter to IActionFilter attribute?

I'm trying to create my custom attribute using IActionFilter:
Attribute:
public class MyAuthorize : TypeFilterAttribute
{
public int Id { get; set; }
public MyAuthorize() : base(typeof(MyAuthorizeImplement))
{
Arguments = new object[] { Id };
}
private class MyAuthorizeImplement : IActionFilter
{
private readonly int _id;
public MyAuthorizeImplement(int id)
{
_id = id;
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
context.Result = new ContentResult
{
Content = $"Id: {_id}"
};
}
}
}
Action:
public class HomeController : Controller
{
[MyAuthorize(Id = 1)]
public IActionResult Index()
{
return View();
}
}
Result content:
Id: 0
I've tried many times with the difference Id values, but _id is still 0 as default. Then I've tried to change the value types of Id, id and _id from int to string and pass some value but it's still null:
[MyAuthorize(Id = "abc")]
Do I miss something? Thank you!
P/S: I also tried this way, it worked but I don't want to use it:
Inside the constructor, tried to use id as a parameter instead of a property:
// public int Id { get; set; }
public MyAuthorize(int id) : base(typeof(MyAuthorizeImplement))
{
Arguments = new object[] { id };
}
Action:
public class HomeController : Controller
{
[MyAuthorize(id: 1)]
public IActionResult Index()
{
return View();
}
}
Result content:
Id: 1
In the first case, the constructor doesn't require any parameter, it's an option but in the second it does. That's why I don't want to use it.
When I need some rule (as Id, Roles, Name...), I can pass it. Otherwise, leave it empty. Just like Authorize attribute:
[Authorize] -> All login user can assign
[Authorize(Roles = "Administrator")] -> Only user with this role can assign

Serializing a collection of view models with overridden Equals method

Trying to serialize a collection of a custom type with an overloaded Equals(object obj) method. I am using Newtonsoft.Json.JsonConvert.SerializeObject(object value) to achieve this.
This is my abstract base view model from which the view model in question inherits:
public abstract class BaseCollectibleViewModel
{
protected abstract bool CompareParameters(object item);
protected abstract List<int> GetParameters();
public override bool Equals(object obj)
{
if (CompareParameters(obj))
{
return true;
}
return false;
}
public override int GetHashCode()
{
int hash = 13;
foreach (var parameter in GetParameters())
{
hash = (hash * 7) + parameter.GetHashCode();
}
return hash;
}
public static bool operator ==(BaseCollectibleViewModel a, BaseCollectibleViewModel b)
{
if (a.Equals(b))
{
return true;
}
return false;
}
public static bool operator !=(BaseCollectibleViewModel a, BaseCollectibleViewModel b)
{
if (a.Equals(b))
{
return false;
}
return true;
}
}
This is the actual view model:
public class ImagesViewModel : BaseCollectibleViewModel, ISourceImage
{
public string Name { get; private set; }
public string Type { get; private set; }
[ScriptIgnore]
public Stream Content { get; private set; }
[ScriptIgnore]
private HttpPostedFileBase _file;
[ScriptIgnore]
public HttpPostedFileBase File
{
get
{
return _file;
}
set
{
_file = value;
Name = File.FileName;
Type = File.ContentType;
Content = new MemoryStream();
File.InputStream.CopyTo(Content);
}
}
protected override bool CompareParameters(object obj)
{
var temp = obj as ImagesViewModel;
if(temp == null)
{
return false;
}
return
(Name == temp.Name &&
Type == temp.Type);
}
protected override List<int> GetParameters()
{
return new List<int>()
{
Name.GetHashCode(),
Type.GetHashCode()
};
}
}
Notice the ScriptIgnore attributes. I even have one on the private field. The program breaks on the == operator of the base class because both of the arguments that get passed are null.
This is the serializing code:
[HttpPost]
public string GetSessionImages()
{
var imagesInSession = _imagesSessionService.GetCollection();
return JsonConvert.SerializeObject(imagesInSession, Formatting.Indented);
}
Also this:
The screenshot is showing the implementation of the abstract CompareParameters(object obj) method on the inheriting view model. That stream is the Content property stream, I have checked. Why is this happening?
EDIT: When not overriding Equals I get a JsonSerializationException stating:
{"Error getting value from 'ReadTimeout' on
'System.IO.MemoryStream'."}
EDIT 2: Per dbc's comment I have replaced the attribute [ScriptIgnore] with [JsonIgnore] and the code worked to an extent.
However, I had to comment out the operator implementations because the '==' operator would be passed a null value as the BaseCollectibleViewModel b argument.
Since you are using json.net, you must mark members to ignore with [JsonIgnore]:
using Newtonsoft.Json;
public class ImagesViewModel : BaseCollectibleViewModel, ISourceImage
{
public string Name { get; private set; }
public string Type { get; private set; }
[ScriptIgnore]
[JsonIgnore]
public Stream Content { get; private set; }
[ScriptIgnore]
[JsonIgnore]
public HttpPostedFileBase File { get { ... } set { ... } }
It is not necessary to mark entirely private members with [JsonIgnore] as these are not serialized by default by Json.NET.
Alternatively, if you do not want your models to have a dependency on Json.NET, you could use conditional property serialization to unconditionally suppress the same members:
public class ImagesViewModel : BaseCollectibleViewModel, ISourceImage
{
public string Name { get; private set; }
public string Type { get; private set; }
[ScriptIgnore]
public Stream Content { get; private set; }
public bool ShouldSerializeContent() { return false; }
[ScriptIgnore]
public HttpPostedFileBase File { get { ... } set { ... } }
public bool ShouldSerializeFile() { return false; }
Note that the ShouldSerializeXXX() conditional serialization pattern is also respected by other serializers including XmlSerializer, as explained in ShouldSerialize*() vs *Specified Conditional Serialization Pattern - a side-effect which may be desirable, or not.
(Incidentally, you might want to check that you are not double-serializing your data as shown in JSON.NET Parser *seems* to be double serializing my objects.)

Categories