I have a question about Claims, JWT, and ASP.Net Core. Again... (Greetings Chris). So...
I have my JWT with Claim:
"Authorization": "CanEditUnit,CanBrowseUnit,CanCreateUnit,CanDeleteUnit,CanSeeUnitDetails,CanBrowseRole,CanEditRole,CanCreateRole,CanDeleteRole,CanSeeRoleDetails,CanBrowseUser,CanSeeUserDetails,CanDeleteUser,CanEditUser,CanRegisterNewUser"
etc.
This Claim has all privileges, that user contains (for example: If the user has CanEditUnit in a database set to True, CanEditUnit is saved in Authorization Claim, but if something is set to False it simply doesn't appear in that Claim.
Then I want to check if user has that Privilages in Policies like that:
options.AddPolicy("CanEditUnit", policy => policy.RequireClaim("Authorization", "CanEditUnit"));
But it probably checks if Authorization Claim is equal to CanEditUnit.
Is there a way to check policies with Contains instead of Equal? If not, what should I do them?
I found this in docs, but I don't know how to use it.
As you've suggested in your question, it looks like RequireAssertion has the ability to handle this for you. Here's an example:
policy.RequireAssertion(ctx =>
{
var authorizationClaim = ctx.User.FindFirstValue("Authorization");
if (authorizationClaim == null)
return false;
return authorizationClaim.Split(",").Contains("CanEditUnit");
});
This simply looks for an Authorization claim and, if it exists, splits it by , and checks for the existence of a CanEditUnit value.
If you want something a little more reusable, you can create a custom AssertionRequirement class of your own. Here's an example of what that might look like:
public class CustomAssertionRequirement : AssertionRequirement
{
public CustomAssertionRequirement(string requiredValue)
: base(ctx => HandleRequirement(ctx, requiredValue)) { }
private static bool HandleRequirement(AuthorizationHandlerContext ctx, string requiredValue)
{
var authorizationClaim = ctx.User.FindFirstValue("Authorization");
if (authorizationClaim == null)
return false;
return authorizationClaim.Split(",").Contains(requiredValue);
}
}
In order to use this new class, you can add it as a requirement to the AuthorizationPolicyBuilder (instead of using RequireAssertion), like so:
policy.AddRequirements(new CustomAssertionRequirement("CanEditUnit"));
I would like to find a good design pattern on how to implement this example business workflow. Instead of using one giant monolithic procedural-like method call, I was thinking I would like to use a fluent method chaining -- basically, a simple workflow pipeline without using one of those workflow or BPM frameworks. Suggestions on best practice, perhaps a known design pattern?
My Example
get configuration / user preferences
validate config/preferences
look up / standardize additional config/preferences
get report 1 (with above input)
get report 2, etc.
email reports
The inputs/user preferences causes a lot of if/else logic, so I don't want to have my method have to contain all my if/else logic to see if each step was successful or not, and handle. (i.e. I do NOT want)
myOutput1 = CallMethod1(param1, param2, our errorMsg)
if (error)
{ // do something, then break }
myOutput2 = CallMethod2(param1, param2, our errorMsg)
if (error)
{ // do something, then break }
...
myOutput9 = CallMethod9(param1, param2, our errorMsg)
if (error)
{ // do something, then break }
Sample Idea Pipeline code
Perhaps something like this? Would it work? How can I improve upon it?
public class Reporter
{
private ReportSettings Settings {get; set;}
private ReportResponse Response {get; set;}
public ReportResponse GenerateAndSendReports(string groupName)
{
ReportResponse response = this.GetInputConfiguration()
.ValidateConfiguration()
.StandardizeConfiguration(groupName)
.PopulateReport1()
.PopulateReport2()
.PopulateReport99()
.EmailReports()
.Output();
return response;
}
public Reporter GetInputConfiguration()
{
this.Response = new ReportResponse();
this.Settings = new ReportSetting();
this.Settings.IsReport1Enabled = ConfigurationManager.GetSetting("EnableReport1");
this.Settings.Blah1 = ConfigurationManager.GetSetting("Blah1");
this.Settings.Blah2 = ConfigurationManager.GetSetting("Blah2");
return this;
}
public Reporter StandardizeConfiguration(string groupName)
{
this.Settings.Emails = myDataService.GetEmails(groupName);
return this;
}
public Reporter PopulateReport1()
{
if (!this.Setting.HasError && this.Settings.IsReport1Enabled)
{
try
{
this.Response.Report1Content = myReportService.GetReport1(this.Settings.Blah1, this.Blah2)
}
catch (Exception ex)
{
this.Response.HasError = true;
this.Response.Message = ex.ToString();
}
}
return this;
}
}
I was thinking of something like this
You are mentioning two distinct concepts: fluent mechanism, and the pipeline (or chain of responsibility) pattern.
Pipeline Pattern
Must define an interface IPipeline which contains DoThings();.
The implementations of IPipeline must contain an IPipeline GetNext();
Fluent
All actions must return a reference to the object modified by the action: IFluent.
If you which to better control what options are available and when in your workflow, you could have the Fluent actions returning distinct interfaces: for example IValidatedData could expose IStandardizedData Standardize(), and IStandardizedData could expose IStandardizedData PopulateReport(var param) and IStandardizedData PopulateEmail(var param). This is what LINQ does with enumerables, lists, etc.
However, in your example it looks like you are mostly looking for a Fluent mechanism. The pipeline pattern helps with data flows (HTTP request handlers, for example). In your case you are just applying properties to a single object Reporter, so the pipeline pattern does not really apply.
For those who ended here because they are looking for a two-way (push and pull) fluent pipeline, you want your fluent actions to build the pipeline, by returning an IPipelineStep. The behaviour of the pipeline is defined by the implementation of each IPipelineStep.
You can achieve this as follows:
PipelineStep implements IPipelineStep
PipelineStep contains a private IPipelineStep NextStep(get;set);
IPipelineBuilder contains the fluent actions available to build the pipeline.
Your fluent actions return a concretion which implement both IPipelineStep and IPipelineBuilder.
Before returning, the fluent action updates this.NextStep.
IPipelineStep contains a var Push(var input); and var Pull(var input);
Push does things and then calls this.NextStep.Push
Pull calls this.NextStep.Pull and then does things and returns
You also need to consider how you want to use the pipeline once built: from top to bottom or the other way around.
I know this is an old question, but this is a pretty recent video explaining how to build a nice Fluent API. One thing mentioned, that I think is great, is the idea of using interfaces to enforce the correct order to call the APIs.
https://www.youtube.com/watch?v=1JAdZul-aRQ
We're building an ASP.NET app, and have a requirement to use the corporate LDAP system (Siteminder) for authentication (upside: no login dialogs). Roles are created in the LDAP tool, and users are assigned to the roles by userland managers (read: the structure has to be easily understood). Currently, all apps that use the system use a dual-entry process whereby the roles identified in the app are hand-entered into the LDAP system and users are assigned, then app functions are assigned to their role mirrors in an app-based control panel. This works, but it bothers me that dual-entry is required.
What I would like to achieve is something where the app queries the LDAP system to get a list of roles that are assigned to the app (which is identified in the LDAP system) and populate the role:function control panel with them. This part seems really straightforward. However, I lose clarity when it comes to figuring out what to put in the Authorize attribute:
[Authorize(Roles = "Admin, Moderator")]
would become... what?
[Authorize(LoadedRoles(r => r.FindAll("some expression that describes the roles that have a particular permission")))]
I'm seriously into blue sky territory here. I read this question, and liked - from an architectural standpoint - the answer that suggested making the permissions the roles. But that might not be acceptable to the userland managers that needed to manage users. On the other hand, this question turns things into non-string resources, but I can't conceive of how to translate that into "roles that have this sort of function included".
Any suggestions?
Update:
Based on the advice of #venerik below, I've made some progress. For the time being, I'm encapsulating everything in the [AuthorizeFunctionAttribute], and will farm the individual pieces out where they belong later. To that end, I created three variables:
private IList<KeyValuePair<long, string>> Roles;
private IList<KeyValuePair<long, string>> Functions;
private IList<RoleFunction> RoleFunctions;
...then put static data in them:
Roles = new ICollection<KeyValuePair<long, string>>();
Roles.Add(KeyValuePair<long, string>(1, "Basic User"));
Roles.Add(KeyValuePair<long, string>(2, "Administrator"));
Functions = new ICollection<KeyValuePair<long, string>>();
Functions.Add(KeyValuePair<long,string>(1,"List Things"));
Functions.Add(KeyValuePair<long,string>(2,"Add Or Edit Things"));
Functions.Add(KeyValuePair<long,string>(3,"Delete Things"));
...and finally bound them together (in a complicated manner that lays the groundwork for the future):
RoleFunctions = new IList<RoleFunction>();
RoleFunctions.Add(
new RoleFunction
{
RoleId = Roles.Where( r => r.Value == "Basic User").FirstOrDefault().Key,
FunctionId = Functions.Where( f => f.Value == "List Things" ).FirstOrDefault().Key,
isAuthorized = true
},
new RoleFunction
{
RoleId = Roles.Where( r => r.Value == "Administrator").FirstOrDefault().Key,
FunctionId = Functions.Where( f => f.Value == "Add or Edit Things" ).FirstOrDefault().Key,
isAuthorized = true
},
// More binding...
);
I feel good about this so far. So I went researching AuthorizeCore to see what I needed to do there. However, per the comment at the bottom of the page, it's not very helpful. I more or less get that at the end, the method needs to return a bool value. And I get that I need to check that one of the User.Roles array fits the permission that's passed in through [AuthorizeFunction("List Things")].
Update (again):
I've got the following code, which seems like it will do what I need (one method needs fleshing out):
/// <summary>An authorization attribute that takes "function name" as a parameter
/// and checks to see if the logged-in user is authorized to use that function.
/// </summary>
public class AuthorizeFunctionAttribute : AuthorizeAttribute
{
private IList<KeyValuePair<long, string>> Roles;
private IList<KeyValuePair<long, string>> Functions;
private IList<RoleFunction> RoleFunctions;
public string Function { get; private set; }
public AuthorizeFunctionAttribute(string FunctionName)
{
Function = FunctionName;
Roles = SetApplicationRoles();
Functions = SetApplicationFunctions();
RoleFunctions = SetRoleFunctions();
}
protected virtual bool AuthorizeCore(HttpContextBase httpContext)
{
bool userIsAuthorized = false;
foreach (string ur in GetUserRoles(httpContext.Current.Request.Headers["SM_USER"]))
{
long roleId = Roles.Where( sr => sr.Value == ur )
.First().Key;
long functionId = Functions.Where( sf => sf.Value == Function )
.First().Key;
// If any role is authorized for this function, set userIsAuthorized to true.
// DO NOT set userIsAuthorized to false within this loop.
if (RoleFunctions.Where(rf => rf.RoleId == roleId && rf.FunctionId == functionId)
.First().isAuthorized)
{
userIsAuthorized = true;
}
}
return userIsAuthorized;
}
Previously I didn't know enough about the underlying bits of creating a custom attribute to get out of my own way. However, this MSDN article told me what should have been obvious to me in the beginning: build it yourself. So, once I get the GetUserRoles() method put together, I should be underway.
I think you can solve this using a custom AuthorizeAttribute. In a project I worked close to they used that to access Active Directory (as described in this answer).
In your case it would look something like:
public class AuthorizeWithLDAPAttribute(string functionName) : AuthorizeAttribute
{
protected virtual bool AuthorizeCore(HttpContextBase httpContext)
{
// check LDAP to verify that user has
// a role that's linked to `functionName`
}
}
Next you can use this attribute on your controllers and/or methods:
[AuthorizeWithLDAP("functionName1")]
public class BlogController : Controller
{
....
[AuthorizeWithLDAP("functionName2")]
public ViewResult Index()
{
return View();
}
}
The controller is now only accessible to users whose role are linked to functionName1 and the method is only accessible to users whose role are linked to functionName1 and functionName2
Trying to manage access to a web site I created some necessary entities
The goal is use a custom permission attribute for some controller's action method of my MVC application.
[Permissions(PermissionType.SomePermissionName, CrudType.CanDelete)]
public ActionResult SomeAction()
{
}
For this operation I have two enums
[Flags]
public enum CrudType
{
CanCreate = 0x1,
CanRead = 0x2,
CanUpdate = 0x4,
CanDelete = 0x8,
}
[Flags]
public enum PermissionType
{
SomePermissionName = 0x1,
//...
}
Now I want the method below to check permissions
public static bool CanAccess(RolePermissions rp, CrudType crudType)
{
var pInfo = rp.GetType().GetProperties();
var res = pInfo.FirstOrDefault(x => x.Name == crudType.ToString());
if(res != null)
{
return Convert.ToBoolean(res.GetValue(rp, null));
}
return false;
}
It works good but is it safe to use reflection here? Is it a good style?
One more question is about such piece of code
var permission = PermissionService.GetByName(permissionType.ToString());
Here I'm trying to get a permission object from a database using some named constant from the PermissionType enum.
In both cases the correct work depends on relationships between enums and some table fields or records. On other side I have a good mechanism of controlling logic (as it seems to me).
Is that a good way?
ANOTHER EDIT
In your case it would make sense to create a readonly property ExistingPermissions for the RolePermissions class, and do the merging of the four booleans into one CrudType within that property getter. Then you can just do rp.ExistingPermissions.HasFlag(permissionToCheck).
EDITED
Thanks to #DevDelivery for pointing out the issue - good catch. Unfortunately the fixed solution isn't as pretty as I was hoping for, so in this case it might make sense to go with #DevDelivery's approach.
Since you have your CrudType as "bitfields", you can use a cleaner approach (less code and better readability):
public static bool CanAccess(RolePermissions rp, CrudType permissionToCheck)
{
CrudType existingPermissions =
SetPermissionFlag(CrudType.CanCreate, rp.CanCreate) |
SetPermissionFlag(CrudType.CanRead, rp.CanRead) |
SetPermissionFlag(CrudType.CanUpdate, rp.CanUpdate) |
SetPermissionFlag(CrudType.CanDelete, rp.CanDelete);
return existingPermissions.HasFlag(permissionToCheck);
}
public static CrudType SetPermissionFlag(CrudType crudType, bool permission)
{
return (CrudType)((int)crudType * Convert.ToInt32(permission));
}
The drawback compared to your solution is that you will have to modify this method in case you add more operations (to the existing CanRead, etc.).
Using reflection has a performance impact and the late-binding means that changing a name of a enum
or property will not get caught by the compiler.
Plus, this code is very hard to understand, thus difficult to maintain.
Here there are only 4 options to check. A simple switch statement is easier, faster, and cleaner.
Using reflection would make sense if you were trying to allow for changes to the database or for third-party components to introduce new permissions.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I know that attributes are extremely useful. There are some predefined ones such as [Browsable(false)] which allows you to hide properties in the properties tab. Here is a good question explaining attributes: What are attributes in .NET?
What are the predefined attributes (and their namespace) you actually use in your projects?
[DebuggerDisplay] can be really helpful to quickly see customized output of a Type when you mouse over the instance of the Type during debugging. example:
[DebuggerDisplay("FirstName={FirstName}, LastName={LastName}")]
class Customer
{
public string FirstName;
public string LastName;
}
This is how it should look in the debugger:
Also, it is worth mentioning that [WebMethod] attribute with CacheDuration property set can avoid unnecessary execution of the web service method.
System.Obsolete is one of the most useful attributes in the framework, in my opinion. The ability to raise a warning about code that should no longer be used is very useful. I love having a way to tell developers that something should no longer be used, as well as having a way to explain why and point to the better/new way of doing something.
The Conditional attribute is pretty handy too for debug usage. It allows you to add methods in your code for debug purposes that won't get compiled when you build your solution for release.
Then there are a lot of attributes specific to Web Controls that I find useful, but those are more specific and don't have any uses outside of the development of server controls from what I've found.
[Flags] is pretty handy. Syntactic sugar to be sure, but still rather nice.
[Flags]
enum SandwichStuff
{
Cheese = 1,
Pickles = 2,
Chips = 4,
Ham = 8,
Eggs = 16,
PeanutButter = 32,
Jam = 64
};
public Sandwich MakeSandwich(SandwichStuff stuff)
{
Console.WriteLine(stuff.ToString());
// ...
}
// ...
MakeSandwich(SandwichStuff.Cheese
| SandwichStuff.Ham
| SandwichStuff.PeanutButter);
// produces console output: "Cheese, Ham, PeanutButter"
Leppie points out something I hadn't realized, and which rather dampens my enthusiasm for this attribute: it does not instruct the compiler to allow bit combinations as valid values for enumeration variables, the compiler allows this for enumerations regardless. My C++ background showing through... sigh
I like [DebuggerStepThrough] from System.Diagnostics.
It's very handy for avoiding stepping into those one-line do-nothing methods or properties (if you're forced to work in an early .Net without automatic properties). Put the attribute on a short method or the getter or setter of a property, and you'll fly right by even when hitting "step into" in the debugger.
For what it's worth, here's a list of all .NET attributes. There are several hundred.
I don't know about anyone else but I have some serious RTFM to do!
My vote would be for Conditional
[Conditional("DEBUG")]
public void DebugOnlyFunction()
{
// your code here
}
You can use this to add a function with advanced debugging features; like Debug.Write, it is only called in debug builds, and so allows you to encapsulate complex debug logic outside the main flow of your program.
I always use the DisplayName, Description and DefaultValue attributes over public properties of my user controls, custom controls or any class I'll edit through a property grid. These tags are used by the .NET PropertyGrid to format the name, the description panel, and bolds values that are not set to the default values.
[DisplayName("Error color")]
[Description("The color used on nodes containing errors.")]
[DefaultValue(Color.Red)]
public Color ErrorColor
{
...
}
I just wish Visual Studio's IntelliSense would take the Description attribute into account if no XML comment are found. It would avoid having to repeat the same sentence twice.
[Serializable] is used all the time for serializing and deserializing objects to and from external data sources such as xml or from a remote server. More about it here.
In Hofstadtian spirit, the [Attribute] attribute is very useful, since it's how you create your own attributes. I've used attributes instead of interfaces to implement plugin systems, add descriptions to Enums, simulate multiple dispatch and other tricks.
Here is the post about interesting attribute InternalsVisibleTo. Basically what it does it mimics C++ friends access functionality. It comes very handy for unit testing.
I've found [DefaultValue] to be quite useful.
I'd suggest [TestFixture] and [Test] - from the nUnit library.
Unit tests in your code provide safety in refactoring and codified documentation.
[XmlIgnore]
as this allows you to ignore (in any xml serialisation) 'parent' objects that would otherwise cause exceptions when saving.
It's not well-named, not well-supported in the framework, and shouldn't require a parameter, but this attribute is a useful marker for immutable classes:
[ImmutableObject(true)]
I like using the [ThreadStatic] attribute in combination with thread and stack based programming. For example, if I want a value that I want to share with the rest of a call sequence, but I want to do it out of band (i.e. outside of the call parameters), I might employ something like this.
class MyContextInformation : IDisposable {
[ThreadStatic] private static MyContextInformation current;
public static MyContextInformation Current {
get { return current; }
}
private MyContextInformation previous;
public MyContextInformation(Object myData) {
this.myData = myData;
previous = current;
current = this;
}
public void Dispose() {
current = previous;
}
}
Later in my code, I can use this to provide contextual information out of band to people downstream from my code. Example:
using(new MyContextInformation(someInfoInContext)) {
...
}
The ThreadStatic attribute allows me to scope the call only to the thread in question avoiding the messy problem of data access across threads.
The DebuggerHiddenAttribute which allows to avoiding step into code which should not be debugged.
public static class CustomDebug
{
[DebuggerHidden]
public static void Assert(Boolean condition, Func<Exception> exceptionCreator) { ... }
}
...
// The following assert fails, and because of the attribute the exception is shown at this line
// Isn't affecting the stack trace
CustomDebug.Assert(false, () => new Exception());
Also it prevents from showing methods in stack trace, useful when having a method which just wraps another method:
[DebuggerHidden]
public Element GetElementAt(Vector2 position)
{
return GetElementAt(position.X, position.Y);
}
public Element GetElementAt(Single x, Single y) { ... }
If you now call GetElementAt(new Vector2(10, 10)) and a error occurs at the wrapped method, the call stack is not showing the method which is calling the method which throws the error.
DesignerSerializationVisibilityAttribute is very useful. When you put a runtime property on a control or component, and you don't want the designer to serialize it, you use it like this:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Foo Bar {
get { return baz; }
set { baz = value; }
}
Only a few attributes get compiler support, but one very interesting use of attributes is in AOP: PostSharp uses your bespoke attributes to inject IL into methods, allowing all manner of abilities... log/trace being trivial examples - but some other good examples are things like automatic INotifyPropertyChanged implementation (here).
Some that occur and impact the compiler or runtime directly:
[Conditional("FOO")] - calls to this method (including argument evaluation) only occur if the "FOO" symbol is defined during build
[MethodImpl(...)] - used to indicate a few thing like synchronization, inlining
[PrincipalPermission(...)] - used to inject security checks into the code automatically
[TypeForwardedTo(...)] - used to move types between assemblies without rebuilding the callers
For things that are checked manually via reflection - I'm a big fan of the System.ComponentModel attributes; things like [TypeDescriptionProvider(...)], [TypeConverter(...)], and [Editor(...)] which can completely change the behavior of types in data-binding scenarios (i.e. dynamic properties etc).
If I were to do a code coverage crawl, I think these two would be top:
[Serializable]
[WebMethod]
I have been using the [DataObjectMethod] lately. It describes the method so you can use your class with the ObjectDataSource ( or other controls).
[DataObjectMethod(DataObjectMethodType.Select)]
[DataObjectMethod(DataObjectMethodType.Delete)]
[DataObjectMethod(DataObjectMethodType.Update)]
[DataObjectMethod(DataObjectMethodType.Insert)]
More info
In our current project, we use
[ComVisible(false)]
It controls accessibility of an individual managed type or member, or of all types within an assembly, to COM.
More Info
[TypeConverter(typeof(ExpandableObjectConverter))]
Tells the designer to expand the properties which are classes (of your control)
[Obfuscation]
Instructs obfuscation tools to take the specified actions for an assembly, type, or member. (Although typically you use an Assembly level [assembly:ObfuscateAssemblyAttribute(true)]
The attributes I use the most are the ones related to XML Serialization.
XmlRoot
XmlElement
XmlAttribute
etc...
Extremely useful when doing any quick and dirty XML parsing or serializing.
Being a middle tier developer I like
System.ComponentModel.EditorBrowsableAttribute Allows me to hide properties so that the UI developer is not overwhelmed with properties that they don't need to see.
System.ComponentModel.BindableAttribute Some things don't need to be databound. Again, lessens the work the UI developers need to do.
I also like the DefaultValue that Lawrence Johnston mentioned.
System.ComponentModel.BrowsableAttribute and the Flags are used regularly.
I use
System.STAThreadAttribute
System.ThreadStaticAttribute
when needed.
By the way. I these are just as valuable for all the .Net framework developers.
[EditorBrowsable(EditorBrowsableState.Never)] allows you to hide properties and methods from IntelliSense if the project is not in your solution. Very helpful for hiding invalid flows for fluent interfaces. How often do you want to GetHashCode() or Equals()?
For MVC [ActionName("Name")] allows you to have a Get action and Post action with the same method signature, or to use dashes in the action name, which otherwise would not be possible without creating a route for it.
I consider that is important to mention here that the following attributes are also very important:
STAThreadAttribute
Indicates that the COM threading model for an application is single-threaded apartment (STA).
For example this attribute is used in Windows Forms Applications:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
And also ...
SuppressMessageAttribute
Suppresses reporting of a specific static analysis tool rule violation, allowing multiple suppressions on a single code artifact.
For example:
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "isChecked")]
[SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "fileIdentifier")]
static void FileNode(string name, bool isChecked)
{
string fileIdentifier = name;
string fileName = name;
string version = String.Empty;
}
Off the top of my head, here is a quick list, roughly sorted by frequency of use, of predefined attributes I actually use in a big project (~500k LoCs):
Flags, Serializable, WebMethod, COMVisible, TypeConverter, Conditional, ThreadStatic, Obsolete, InternalsVisibleTo, DebuggerStepThrough.
I generates data entity class via CodeSmith and I use attributes for some validation routine. Here is an example:
/// <summary>
/// Firm ID
/// </summary>
[ChineseDescription("送样单位编号")]
[ValidRequired()]
public string FirmGUID
{
get { return _firmGUID; }
set { _firmGUID = value; }
}
And I got an utility class to do the validation based on the attributes attached to the data entity class. Here is the code:
namespace Reform.Water.Business.Common
{
/// <summary>
/// Validation Utility
/// </summary>
public static class ValidationUtility
{
/// <summary>
/// Data entity validation
/// </summary>
/// <param name="data">Data entity object</param>
/// <returns>return true if the object is valid, otherwise return false</returns>
public static bool Validate(object data)
{
bool result = true;
PropertyInfo[] properties = data.GetType().GetProperties();
foreach (PropertyInfo p in properties)
{
//Length validatioin
Attribute attribute = Attribute.GetCustomAttribute(p,typeof(ValidLengthAttribute), false);
if (attribute != null)
{
ValidLengthAttribute validLengthAttribute = attribute as ValidLengthAttribute;
if (validLengthAttribute != null)
{
int maxLength = validLengthAttribute.MaxLength;
int minLength = validLengthAttribute.MinLength;
string stringValue = p.GetValue(data, null).ToString();
if (stringValue.Length < minLength || stringValue.Length > maxLength)
{
return false;
}
}
}
//Range validation
attribute = Attribute.GetCustomAttribute(p,typeof(ValidRangeAttribute), false);
if (attribute != null)
{
ValidRangeAttribute validRangeAttribute = attribute as ValidRangeAttribute;
if (validRangeAttribute != null)
{
decimal maxValue = decimal.MaxValue;
decimal minValue = decimal.MinValue;
decimal.TryParse(validRangeAttribute.MaxValueString, out maxValue);
decimal.TryParse(validRangeAttribute.MinValueString, out minValue);
decimal decimalValue = 0;
decimal.TryParse(p.GetValue(data, null).ToString(), out decimalValue);
if (decimalValue < minValue || decimalValue > maxValue)
{
return false;
}
}
}
//Regex validation
attribute = Attribute.GetCustomAttribute(p,typeof(ValidRegExAttribute), false);
if (attribute != null)
{
ValidRegExAttribute validRegExAttribute = attribute as ValidRegExAttribute;
if (validRegExAttribute != null)
{
string objectStringValue = p.GetValue(data, null).ToString();
string regExString = validRegExAttribute.RegExString;
Regex regEx = new Regex(regExString);
if (regEx.Match(objectStringValue) == null)
{
return false;
}
}
}
//Required field validation
attribute = Attribute.GetCustomAttribute(p,typeof(ValidRequiredAttribute), false);
if (attribute != null)
{
ValidRequiredAttribute validRequiredAttribute = attribute as ValidRequiredAttribute;
if (validRequiredAttribute != null)
{
object requiredPropertyValue = p.GetValue(data, null);
if (requiredPropertyValue == null || string.IsNullOrEmpty(requiredPropertyValue.ToString()))
{
return false;
}
}
}
}
return result;
}
}
}
[DeploymentItem("myFile1.txt")]
MSDN Doc on DeploymentItem
This is really useful if you are testing against a file or using the file as input to your test.
[System.Security.Permissions.PermissionSetAttribute] allows security actions for a PermissionSet to be applied to code using declarative security.
// usage:
public class FullConditionUITypeEditor : UITypeEditor
{
// The immediate caller is required to have been granted the FullTrust permission.
[PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
public FullConditionUITypeEditor() { }
}