Winforms method/event filter attribute - c#

I have been working with ASP.NET MVC for over a year now. I love ASP.NET MVC. In the meantime, every now and then I develop a Windows Forms Application. This application allows our customers to create a group structure for their webshop.
For that purpose I use a TreeView. How does this relate to ASP.NET MVC? Well, MVC has these action filter attributes that come in quite handy and makes the code better readable (in my opinion). I mean filters like for example the [Authorize] attribute, which stops the action from executing if the user is not authorized.
So the actual question is, can a simular filter be created for the methods and events in a Windows Forms Application? I need to check (in a lot of methods and events) if the SelectedNode property of the TreeView has a value. Now I do that this way:
private void setSelectedGroupInformation(bool refreshProductCount)
{
GroupNode selectedNode = trvGroupTree.SelectedNode;
if (selectedNode == null || !selectedNode.HasGroup)
return;
// Code that actually DOES something
}
But it would be nice if this would be possible:
[SelectedNodeRequired]
[GroupRequired]
private void setSelectedGroupInformation(bool refreshProductCount)
{
// Code that actually DOES something
}
That is much better readable. I checked out the internet for this but I can't find a similar question.

It might be nice, but you need to do some work for it (one example, is constructing a type at runtime). What is relatively easy to do is to call some common method at first
[SelectedNodeRequired]
[GroupRequired]
private void setSelectedGroupInformation(bool refreshProductCount)
{
if(MethodTester())
return;
// Code that actually DOES something
}
bool MethodTester()
{
// use call stack to get caller method name
// use reflection to get attributes of method
// check attributes and conditions
...
return true; // if has to be filtered
...
return false;
}
But, why not making methods what actually does all logic you need to check? Like this
private void setSelectedGroupInformation(bool refreshProductCount)
{
if(Global.IsGroupRequired && Global.IsSelectedNodeRequired)
{
// Code that actually DOES something
}
}

Related

How to add backing variable for property with ReSharper

I have created property from code with ReSharper (moved from some method that was too long):
private static SomeFunctions XmlSomeFunctions
{
get
{
// some logic
return someFunctions;
}
}
However, I want it to be something like this:
private static SomeFunctions xmlSomeFunctions;
private static SomeFunctions XmlSomeFunctions
{
get
{
if (xmlSomeFunctions == null)
{
// some logic
xmlSomeFunctions = someFunctions;
}
return xmlSomeFunctions;
}
}
But I have not found any entry in context menu (Ctrl+Shift+R = Refactor This) in ReSharper that could help me with this task. Is there any way I can create above code automatically with ReSharper?
If I won't rewrite this code (manually for now, preferably with ReSharper, if I know how), I will have that logic executed many times (instead of once) if I ask for XmlSomeFunctions in different places in my code.
What your actually trying to do is create a lazily instantiated property. A better way to do this is just use the Lazy class in .Net. Reuse this class instead of trying to automate the repetitive code with resharper would be my advice.
See http://msdn.microsoft.com/en-us/library/dd642331(v=vs.110).aspx
You do have this possibility. Place your cursor on the name of the property (XmlSomeFunctions) and click on the hammer icon to the left.
You'll have to add the if statement yourself though.

ASP.Net C# - Moving Code from Codebehind to Class File

For some time now I am trying to figure out how I can refactor some of my code to reduce redundancy throughout my application. I am just learning the basics of OOP and can create simple classes and methods but my knowledge is limited in terms of practical applicability. The following bit of code illustrates my frustration:
#region DELETE selected users - button
protected void btnDeleteSelected_Click(object sender, EventArgs e)
{
try
{
foreach (GridViewRow row in GridView1.Rows)
{
CheckBox cb = (CheckBox)row.FindControl("chkRows");
if (cb != null && cb.Checked)
{
// get the row index values (DataKeyNames) and assign them to variable
string userName = GridView1.DataKeys[row.RowIndex].Value.ToString();
// delete selected users and their profiles
ProfileManager.DeleteProfile(userName);
Membership.DeleteUser(userName);
Msg.Text = "User(s) were sucessfully <b>DELETED</b>!";
Msg.Visible = true;
}
}
}
catch (Exception ex)
{
Msg.Text = "Oops! " + ex.Message;
Msg.Visible = true;
}
finally
{
// refresh gridview to reflect changes
GridView1.DataBind();
}
}
#endregion
This bit of code is used on several pages of my project in the pages codebehind file. How can I move this to a class file. I don't know how to reference an object like a gridview in a class because it does not exist like it does on the actual page.
Could some one help out please? Thank you.
There are many principles that you generally apply when trying to refactor code. Currently, you're trying to refactor your code as to not violoate the DRY principle (DRY = don't repeat yourself). It would be a great move to refactor that code.
But, some other principals might come in to play that you might want to consider. The single responsibility principle would suggest that each method does only one unambiguous thing. Think about the operations your current method does. It extracts the usernames from the GridView, and then deletes some data associated with that user. That might be better off as two methods.
Also, loosely coupled code is good. You don't want a bunch of dependencies between your classes. For example, if you moved your whole method, as is, to a separate class or library, that class or library would be dependent on the ASP.NET libraries, because it makes a specific reference to the GridView control. But it doesn't need to. You could have a separate method that pulls the username out of the GridView (this method would be tightly coupled with ASP.NET), and then a separate one that does the rest of your actions (such as deleting the user's data), which only requires the username. That second method would not be coupled to ASP.NET in any way. So by having separate methods that each have a single responsibility, you'll have more loosely coupled code. Two for one.
As for what you said here:
I don't know how to reference an
object like a gridview in a class
because it does not exist like it does
on the actual page.
You'd just want to pass a reference to your GridView when you call the method that would extract the usernames. Something like this:
public static class Util
{
public static IEnumerable<string> GetUsernames(GridView gv)
{
List<string> userNames = new List<string>();
foreach (GridViewRow row in gv.Rows)
{
CheckBox cb = (CheckBox)row.FindControl("chkRows");
if (cb != null && cb.Checked)
{
// get the row index values (DataKeyNames) and assign them to variable
string userName = gv.DataKeys[row.RowIndex].Value.ToString();
userNames.Add(userName);
}
}
return userNames;
}
}
Now, in any of your asp.net code behind pages, you can do:
IEnumerable<string> usernames = Util.GetUsernames(GridView1);
foreach(string username in usernames)
doSomething(username);
The doSomething(username) would be a call to some other method that does your delete operations, or whatever you want.
Hope this helps.
Oh, and if you're just learning the basics of OOP, I would recommend something like Head First Object-Oriented Analysis and Design, or any book that seems to adequately cover the subject. I like the O'Reilly Head First series. The information is very digestible.
In Webforms applications, a common technique for factoring out application and/or business logic out of the code behind is to use the MVP pattern. This doesn't mean all the code typically found in the code-behind just gets moved to another class, as this really isn't any different than a code-behind. The UI rendering logic (e.g. Databinding setup, access to UI controls, etc.) is best left to the code-behind, but the business logic (in this case, the removal of users) is performed by a method within the Presenter.
In your case, I would build up a collection of usernames and call a RemoveUsers() method on the Presenter, passing in the list of usernames, which would handle interfacing with the ProfileManager and Membership components(ideally through abstractions). This allows you to write unit tests for the logic within the Presenter.

a basic issue in implementing validations through properties ? Please guide me

thanks for your attention and time.
I want to implement validations in settter of properties. Here is an issue where your expert help is required please.
I have idea of how I will do validations before setting value. but not getting what to do if passed value is not correct. Just not setting is not a acceptable solution as I want to return an appropriate message to user (in a label in web form). My example code is:
private int id;
public int Id
{
get
{ return id; }
set
{
bool result = IsNumber(value);
if (result==false)
{
// What to do if passed data is not valid ? how to give a appropriate message to user that what is wrong ?
}
id = value;
}
}
A thought was to use return but it is not allowed.
Throwing error looks not good as generally we avoid thorwing custom errors.
Please guide and help me.
thanks in anticipation
haansi
You could consider throwing appropriate exception from property setter. That way it will be clear to the calling party what went wrong, especially assuming you have business rules with respect to setting properties. Of course you do expect the caller to do validations, if still there is a problem, then throwing exception doesn't seem that bad.
"It is valid and acceptable to throw exceptions from a property setter."
Property design guidelines
Best practices: throwing exceptions from properties
What exception to throw from a property setter?
I think you'd better change to another example because:
public int Id
{
get { ... }
set
{
if (!IsNumer(value)) // changes to if (value>5)
{
//the code here will never be executed
id = value;
}
}
}
If the check is only about number (type) then your property can very well handle the type safety. Eg. User wont be able to assign string to a property accepting int.
I would suggest that if Property involves certaing computations, then one should consider using a method instead. In that case, you will option to get some text in return.
One more option is to store all these validation checks in an instance collection (inside the same object). Like.
private List _faileValdations;
//more code
set
{
if (!IsNumber(value))
{
_faileValdations.Add("Invalid value for xxx. Expected... got..");
}
else{
id = value;
}
}
And then, your GUI can read the FailedValidations collection in the end, and display it in a formatted way in some label.
Edit: one more option below.
Sorry i forgot to mention about this before.
You can use an event driven approach also.
You object can expose an event like "ValidationFailed", and all the GUI objects can subscribe to this event. The object will trigger this event in case any validation is failed in the setters.
set {
if (!IsNumber(value))
{
RaiseValidationFailed("some message");
}
else{
id = value;
}
}
"RaiseValidationFailed" can collect the message, wrap it up in some event args and trigger "ValidationFailed" event with the message. Then GUI can react to this.
{I can provide you a full code for this if its not clear}
I would argue that you should rethink your approach to validation. The approach that you are suggesting means that every time a property changes, a message will be generated.
How will these messages be collected, stored and presented? Especially if you decide to use your classes in a website?
What if you want to validate your class at any other time?
What if you want to use the same rules in client side validation?
I can understand the appeal of catching an invalid value as early as possible, but it is a lot easier to validate an entire class in one call such as a Validate() method. This way, you have full control over when the validation logic is run.
I would recommend you read up on the two leading approaches to property validation:
Data Anotations
Fluent Validation for >NET 3.0 and above
Fluent Validation for .NET 2.0
Both Data Annotations and FluentValidation are easy to use and they are able to generate well-tested client side validation on web forms and win forms.
In Data Annotations, the validation is added to the properties using attributes. If you prefer to keep your data classes as clean data transfer objects, Fluent validation involves the creation of easily readable rules in Validator classes.

Allow or disallow method run in .NET

I need to organize some simple security in a class depends on value of the enum.
All that I can figure out is using attribute on a method and then run check then if it fails throw an exception.
Sample:
[ModulePermission(PermissonFlags.Create)]
public void CreateNew()
{
CheckPermission();
System.Windows.Forms.MessageBox.Show("Created!");
}
protected void CheckPermission()
{
var method = new System.Diagnostics.StackTrace().GetFrame(1).GetMethod();
if (!flags.HasFlag(method.GetCustomAttributes(true).Cast<ModulePermissionAttribute>().First().Flags))
{
throw new ApplicationException("Access denied");
}
}
is there more elegant or simple way to do this, like just to trigger an event when method run?
Why not just use standard Code Access Security instead of reimplementing the attribute handling and stack walking?
I think that if you read through the linked documentation, you'll see that what you have is nowhere close to what is needed to achieve actual security. Thankfully, this hard problem has already been solved...
Not with an enum, but with strings - voila (enforced by the runtime, even in full-trust):
public static class PermissionFlags {
public const string Create = "Create";
}
[PrincipalPermission(SecurityAction.Demand, Role = PermissionFlags.Create)]
public void CreateNew() {
System.Windows.Forms.MessageBox.Show("Created!");
}
All you need to do now is to represent the user as a principal. This is done for you in ASP.NET, and there is a winform plugin (in VS2008 etc) to use ASP.NET for membership. It can be configured for vanilla winforms and WCF, too; at the most basic level, GenericPrincipal / GenericIdentity:
// during login...
string[] roles = { PermissionFlags.Create /* etc */ };
Thread.CurrentPrincipal = new GenericPrincipal(
new GenericIdentity("Fred"), // user
roles);
But you can write your own principal / identity models easily enough (deferred / cached access checks, for example).
You might want to look at doing this with something like PostSharp, which will give you a framework for applying the attributes so that you don't have to run the check in your method. This may, however, increase the complexity depending on how the currently active flags are accessed. You'd probably need some class to cache the current permissions for the current user.
You could take a look at Aspect Oriented Programming.
Check out Postsharp for instance, which will enable you to 'weave' some additional logic at compile time in the methods that you've decorated with your ModulePermission attribute.
By doing so, you will not have to call the 'CheckPermission' method anymore inside that 'secured' method, since that logic can be weaved by Postsharp.
(A while ago, I've been playing around with Postsharp: http://fgheysels.blogspot.com/2008/08/locking-system-with-aspect-oriented.html )

ASP C# How to program neat GUI code

For about a few months i'm programming ASP C#. I always program a lot code in the events and in the load event i check the querystring for valid data. This is some sample code i have in one of my projects:
protected void Page_Load(object sender, EventArgs e)
{
if (Controller.Manual == null)
{
Response.Redirect("login.aspx");
}
lblLocation.Text = "<a href='viewdocument.aspx'>" + Controller.Manual.Title + "</a>";
if (Request.QueryString["gchap"] != null)
{
if (Controller.IsNumeric(Request.QueryString["gchap"].ToString()))
{
genchap = Convert.ToInt32(Request.QueryString["gchap"]);
FillGeneralList();
SetChapterTitle();
}
}
if (Request.QueryString["qchap"] != null)
{
if (Controller.IsNumeric(Request.QueryString["qchap"].ToString()))
{
qualchap = Convert.ToInt32(Request.QueryString["qchap"]);
FillQualityList();
SetChapterTitle();
}
}
// Check document Id is set (did)
if (Request.QueryString["did"] != null)
{
if (Controller.IsNumeric(Request.QueryString["did"].ToString()))
{
docId = Convert.ToInt32(Request.QueryString["did"]);
DetermineView();
}
}
}
I know there must be a way to accomplish this on a more neat way. And this is just the load event. On other events, like click and onchange events i have similar code. I think this is spaghetti code and not well-arranged. So can you tell me how i can arrange my code?
EDIT:
What i want to know is, is there a more neat way to, let's say, fill a listbox? And where do i check whether a querystring value has valid data? Where do i check whether the (input/querystring) data is a number? And where should you put the code that validates the Querystring? Also in the load event?
I feel your pain with some of the organization issues with ASP.NET websites. I've had similar code to yours on several projects.
If you have the choice of your frameworks you might look into ASP.NET MVC. This allows you to have clear separation between the View (Html), the Controllers (All actions and business logic) and the Model (database). That way you have zero code in your codebehind files, it all stays nice and neat in controllers.
Try using TryParse (for example) and you can simplify all the code that looks like
xx.IsNumeric(Request.QueryString["qchap"].ToString())
and
Convert.ToInt32(Request.QueryString["gchap"]);
and reduce the number of calls to Request.QueryString variables
You could try something like
Original code
if (Request.QueryString["gchap"] != null)
{
if (Controller.IsNumeric(Request.QueryString["gchap"].ToString()))
{
gchap = Convert.ToInt32(Request.QueryString["gchap"]);
FillGeneralList();
SetChapterTitle();
}
}
Suggestion
int? gchap; //nullable types thanks Richard :D
if (!int.TryParse(Request.QueryString["gchap"], out id)) {gchap = null};
if (gchap != null) {
FillGeneralList();
SetChapterTitle();
}
// you could make this neater with your own little method
Have a look at this post How do you test your Request.QueryString[] variables?
Try capturing the repetitive code in a separate function. (qchap / gchap)
e.g.:
qualchap = ConvertFillAndSet(Request.Querystring["qchap"]);
genchap = ConvertFillAndSet(Request.QueryString["gchap"]);
private int ConvertFillAndSet(string qrystring)
{
int numberToReturn = 0;
//if the conversion was ok -> true, else false
if (Int32.TryParse(qrystring,numberToReturn))
{
FillQualityList();
SetChapterTitle();
}
//returns 0 if tryparse didn't work
return numberToReturn;
}
Where to start. Unfortunately despite other comments, you're not really writing anything that is 'web forms' specific. So moving to MVC isn't going to magically make your code better.
1 Don't roll your own authentication: Use forms authentication unless you have a compelling reason not to. When using forms authentication, you don't need to write code on every page to check that you're logged in. The framework handles that for you.
2 Learn to use the server controls:
Also as others write you shouldn't be writing html in code, especially for something so trivial. Web forms doesn't make you do this either.
<!-- this is in MyPage.aspx -->
<asp:HyperLink id="viewLink" runat="server" />
// in the code-behind file MyPage.aspx.cs
viewLink.NavigateUrl = "~/viewdocument.aspx";
viewLink.Text = Controller.Title;
If you're going to stick with web forms, you need to get familiar with the ASP.Net Page life-cycle
3 Your code is in need of refactoring. No matter if it's web forms, php, or MVC. Here are some basic refactorings, and none of this is really .net specific. I'll walk through these in small steps.
// this may be a good candidate for an extension method
int? ConvertNullable(string nullableInt) {
if( string.IsNullOrEmpty(nullableInt) )
return null;
int value;
if( Int32.TryParse(nullableInt, out value) )
return value;
return null;
}
which then allows you to write.
int genchap? = ConvertNullable(Request.QueryString["gchap"]);
int qualchap? = ConvertNullable(Request.QueryString["qualchap"]);
int docId? = ConvertNullable(Request.QueryString["did"]);
FillQualityList(genchap,qualchap);
SetChapterTitle(genchap,qualchap);
DetermineView(docId);
but passing a lot of primitives around is a hassle and prone to errors, so sometimes we make a small class to encapsulate the data, in this case the page initialization information.
class ChapterView
{
public int? GenChapter {get; set;}
public int? QualChapter {get; set;}
public int? DocumentId {get; set;}
}
private ChapterView GetChapterView()
{
return new ChapterView
{
GenChapter = ConvertNullable(Request.QueryString["gchap"]),
QualChapter = ConvertNullable(Request.QueryString["qualchap"]),
DocumentId = ConvertNullable(Request.QueryString["did"])
}
}
Note that I've no idea what GenChap and QualChap are, but they're a bit terse and you could complete the refactoring to make them more readable in code. But even without better names, we now have more readable code.
ChapterView chapterView = GetChapterView();
FillQualityList(chapterView);
SetChapterTitle(chapterView);
DetermineView(chapterView);
And finally you may determine that you don't really need to call this every time the page executes to read from the query string. If you've read up on the Asp.Net Page LifeCycle you know that events may change GenChapter or something else that affects how the page is rendered. You may find it better to set up the view in the PreRender instead of calling FillQualityList over and over again.
ChapterView chapterView;
Page_Load()
{
if( !IsPostback )
{
ChapterView chapterView = GetChapterView();
}
else
{
chapterView = (ChapterView) ViewState["chapterview"];
}
}
NextChapter_Click()
{
chaperView.NextChapter();
}
Page_PreRender()
{
FillQualityList(chapterView);
SetChapterTitle(chapterView);
DetermineView(chapterView);}
// make sure class is marked [Serializable]
ViewState["chapterview"] = chapterView;
}
you should follow layered approach. ie: put all your data access code in data access layer, put all your business logic (which also includes validations) in your business layer, put all your model code in your business object layer
and finally for ui - try to never generate html mark up from within the code as far as possible. also, always create a root class for your aspx pages where it has common methods already implemented. then subclass this root class for every other aspx pages
if you are going to hardcode html markup within your c# code - i can assure you this would always result in a lot of chaos (based on my own experience)
but there are situations where you simply cant avoid it. for such cases - this is what i do - i get rid of the code behind and simply put that code in my aspx / ascx file itself. that way when i have to change my ui based on never ending client requests, i dont have to recompile my code - i simply replace my aspx / ascx files on the staging / production server.
you know how clients are : hmmm can u make the black strip look a bit like gray, can u increase the spacing between lines, can u change the text of this hyper link... requests like these never seem to end :-)

Categories