How do I use ValidateDecimal attribute in Castle.ActiveRecord? - c#

I have a class that inherits ActiveRecordValidationBase that contains the following property:
[Property]
[ValidateDecimal]
public Decimal UnitCost { get; set; }
I also have a UnitCostTextBox that accepts input for said UnitCost.
What I would like to do is perform validation once using Castle's validators. However, it seems that before I can pass UnitCodeTextBox.Text to my object, I will need to first convert it to a decimal first.
If I have an erroneous input, an exception will be thrown. So this means I still have to perform regex validations and converting the string to a decimal type before handing it over to Castle.ActiveRecord.
Doesn't this mean it's redundant to have a [ValidateDecimal] since I've already sanitized UnitCost?
I'm wondering how do you guys do it? I have googled for examples, but most of them only handle [ValidateNonEmpty] or [ValidateEmail] which are all strings anyway, not different data types

What you're missing is the binding part (actually you're doing it manually). Castle.Components.Binder and Castle.Components.Validator are used together to automatically bind and validate string input (e.g. an HTML form) into strongly typed objects.
MonoRail does this with the [DataBind] attribute and the AR-specific [ARDataBind]
In a WebForms application you'll have to implement binding+validation yourself (you can of course use Castle.Components.Binder and Castle.Components.Validator)

Related

Is it possible to bind Route Value to a Custom Attribute's Property in ASP.NET Core Web API?

I've a Custom Attribute which I'm using to authorize the request before it hits the Controller Action, in ASP.NET Core Web API. In the image below, "SecureMethod" is the custom attribute.
I want to add a property in the Custom Attribute, which I want to bind to one of the Route Values, please refer to the image below:
I want to bind "userIDs" route-value to one of the Custom Attribute's property ("UserIDs", this is an example attribute).
Is there any way I can bind the route-value to a custom-attribute's property?
TIA
One way you can do this is by passing the name of the route parameter to the attribute, and examining the route data in the attribute itself. For example:
[SecureMethod(PermissionRequired = AccessPermissionEnum.DeleteUsers, UserIdsKey = "userIds")]
Then something like:
public AccessPermissionEnum PermissionRequired { get; set; }
public string UserIdsKey { get; set; }
public override void OnActionExecuting(ActionExecutingContext context)
{
// Depending on how you pass your userIds to the action, you
// may need to use something else from context to get the data,
// but it's all available in there.
var userIds = context.ActionArguments[UserIdsKey];
// Do something with the ids.
base.OnActionExecuting(context);
}
Whilst this works, and in certain places it works really well, you should be aware that the filter now has intimate knowledge of the parameter being passed in. For the most part, this usually doesn't matter so much, but it's an approach you shouldn't use everywhere because it will end up adding a lot of coupling if not used well. It's a useful tool to use every now and then.
No, it is not possible.
Attribute parameters are restricted to constant values of the following types:
Simple types (bool, byte, char, short, int, long, float, and double)
string
System.Type
enums
object (The argument to an attribute parameter of type object must be
a constant value of one of the above types.)
One-dimensional arrays of any of the above types
You cannot nest attributes and you cannot pass non-constant values to attribute parameter. Even though you can declare an attribute parameter as type object, the actual argument you pass in must still be a constant string, bool, etc (declaring it as an object just means you can use any of these types each time you declare the attribute).

.Net Core Binding to a Specific Model given a Specific QueryString Value

I'm in the middle of refactoring an analytics api which needs to allow clients to send events as HTTP GET requests, with their "Hit" data encoded in the URL's QueryString Parameters.
My API's job is to recieve these events, and then place the "valid" events onto a queue in another part of the system for processing.
Some Hits have the same shape. The only thing that makes them different is the value of the type parameter, which all events must have at a minimum.
The problem I've encountered is that based on the Hit type, I'd like to be able to assume the type of each field given to me, which requires model binding. Of course. Currently, I can only find out what model to validate against after checking the value of type - which risks making the API excessively "stringly typed"
An example route would be:
GET https://my.anonymousanalytics.net/capture?type=startAction&amount=300&so_rep=true
Therefore, my Hit would be:
{
type: "startAction",
amount: 300,
so_rep: true
}
Which, hypothetically, could be bound to the Model StackOverflowStartHitModel
class StackOverflowStartHitModel {
public string type { get; } // Q: Could I force the value of this to be "startAction"?
? public int amount { get; }
public boolean so_rep { get; }
}
Why am I asking this here? Well I'm normally a JavaScript developer, but everyone who I'd normally turn to for C# wisdom is off work with the flu.
I have experimented with the [FromQuery] attribute decorator, but my concern is that for Hits that are the exact same shape, I might not be able to tell the difference between whether it is a startAction or an endAction, for example.
you're going to need to have a validation engine of some sort, but do not confuse this with your UI model validation. It sounds like you really have one model with a number of valid states which really is business logic.
Your model looks like this:
public class StackOverflowModel
{
public string type { get; set;}
public int amount { get; set; }
public bool so_rep { get; set;}
}
it doesn't matter what value your type field has and you don't need to hard-code it either, it will be captured as is and then it can be checked against valid states.
There are a number of ways to do this, that I can think of.
One option would be to create a list of valid rules ( states ) and then simply check if your input model matches any of them. One way to implement something like this could be with a library like FluentValidation. You can see an example here: Validation Rules and Business Rules in MVC
Another option would be to use some sort of Pattern Matching techniques like described here: https://learn.microsoft.com/en-us/dotnet/csharp/pattern-matching
Whichever option you go with, make sure you put this validation stuff in a separate class, maybe even a separate project. You can then add tests for each rule that you have to make sure everything works. This will also keep your controller light.
You haven't given examples of valid and invalid states, but I am guessing you're really talking about variations of those 3 parameters such as, when type is "something" then amount can only be < 200 and so_rep can only be "whatever". This can be done quite nicely with the FluentValidation library.

Using Data Annotations with Resources.Messages C#

i'm a student and beginner developer.
I'm on a project on my workplace.. and I'm using Data Annotations for validation... but I need to use Resources.Messages to implement dynamic error messages. Here goes an example of what I'm trying to do:
[Required (ErrorMessage = (string.Format(Messages.MissingParameter, Messages.Ad)))]
[Range(0, long.MaxValue)]
public long? Ad { get; set; }
In this scenario, missing parameter is the follow string "The parameter {0} is required" and Messages.Ad is a string with the internacionalized field.
Soo, if I use Data Annotation, there's a few solutions, like using the ErrorResource... (like this RegularExpressions example -> Why can't I use resources as ErrorMessage with DataAnnotations?)
But these don't contemplate the issue of passing strings that use parameters to deliver the final string (as illustrated on string.format)
So, my question is: How to use complex internationalization string's with data Annotations.
You can't because you have to use specific values that are able to be used as attribute parameters.
From MSDN - Attributes Tutorial C# :
Attribute parameters are restricted to constant values of the following types:
Simple types (bool, byte, char, short, int, long, float, and double)
string
System.Type
enums
object (The argument to an attribute parameter of type object must be a constant value of one of the above types.)
One-dimensional arrays of any of the above types

Difference between Display and Description attribute

I'm trying to enhance my enum so I've tried a suggestion on Display and another one on Description.
I'm annoyed because I don't understand the difference between them. Both Description class and Display class are from framework 4.5.
It's additionally annoying since neither of them work in the code. I'm testing the following but I only get to see the donkeys...
[Flags]
public enum Donkeys
{
[Display(Name = "Monkey 1")]
Donkey1 = 0,
[Description("Monkey 2")]
Donkey2 = 1
}
Neither of these attributes have any effect on the enum's ToString() method, which is what gets called if you just try to insert it into a Razor template. ToString() always uses the name declared in code -- Donkey1 and Donkey2 in your case. To my knowledge, there's no built-in way to specify an alternate string representation for the enum to use automatically.
I assume there are (at least) two reasons for that:
Serialization. ToString() uses the name so that Enum.Parse() can parse it back into the enum.
Localization. .NET was designed with global audiences firmly in mind, and if you want a human-readable string representation of an enum, it's extremely unlikely that there will be just one string representation, at which point it's going to be up to your application to figure out how to do it.
If you know your app will never be translated to other languages, or if you just want a string representation you can use in debug output, you're welcome to use an attribute (either one from the Framework, or one you declare yourself) to define a string representation for each enum value, and write some utility functions to do the string conversion. But you can't make the enum's ToString() do it for you (since that would break serialization); you'd have to write your own code to do it.
However, since you're writing a Web app, there's a fair chance that you will have a global audience -- in which case you'll need to localize your enum strings the same way you localize all your other text.

String parsing to a model (RegEx model binder?)

Is there any elegant way to bind a string to a model, short of writing a bunch of boilerplate code to do the binding myself? Essentially I have a command line interface to a 3rd party device, via telnet. I am building a web service to expose this CLI to external applications. After issuing the command via telnet, I get a response string back, and need to parse this into a model.
Example:
/> echosnd -if 1 -dn 5551234567
Echo Sounder Test created on Interface CITYCOTTNNN-5ES, Resource 12 with ID #2967232
/>
And I want to bind that string to create the following object:
public class ConfigureTestResponse
{
[CLIResponse(RegEx = "Interface (?<interface>[a-zA-Z0-9]*")]
public string Interface { get; set; }
[CLIResponse(RegEx = "Resource (?<resource>[0-9]*)")]
public int Resource { get; set; }
[CLIResponse(RegEx = "#(?<id>[0-9]*)")]
public int TestId { get; set; }
}
To start, I created the CLIResponseAttribute to hold the RegEx filter for that property (although the filters above very possibly don't work - I stuck them in for illustration, only TestId is tested [a little]). I can get them split into groups using Regex, and set the properties that way, but there is a bunch of conversions that I would need to handle (int32, int64, decimal, string, complex model, etc...) based on what the property type is. I am hoping there is some sort of binding that I could provide a name/value pair to, and it would do the appropriate binding - or something even better...
Is there anything out like that? I though of using the MVC DefaultModelBinder, but there would be a good amount of overhead to use it. It would be nice to handle complex types (and lists) that are flattened in a string. What I don't want to do it write specific parsers for each command, as each returns the result in slightly different formats.
Thanks!
(Edit: I would like to move the regex into an attribute on the class, to be able to do an IsMatch on the string. Using groups, I assume I could still bind with the output to the properties.)
Nope, no magic that does it for you there. Better get started! :)

Categories