Continuing from the previous article Securing Dynamic Data Preview 4 Refresh – Part 2 we will proceed to complete the series by finishing off the hyperlinks so you have the option of them all showing as disabled or all being hidden.
The reasoning behind this extra bit to the series (if you can call two articles a series) is I don’t like
- Dead hyperlinks when you mouse over you get the hyperlink action i.e. underline.
- I like consystancy i.e. some links hidden and some shown as dead I want it all to be the same.
So to complete this we will add a new web user control called DynamicHyperLink.ascx which will wrap the asp:DynamicHyperlink control.
%@ Control Language="C#" AutoEventWireup="true" CodeBehind="DynamicHyperLink.ascx.cs" Inherits="DD_EF_SecuringDynamicData.DynamicData.DynamicHyperLink" %> <asp:DynamicHyperLink ID="DynamicHyperLink1" runat="server" onprerender="DynamicHyperLink1_PreRender"> </asp:DynamicHyperLink> <asp:Literal ID="Literal1" runat="server"> </asp:Literal>
Listing 1 - DynamicHyperLink.ascx
public partial class DynamicHyperLink : System.Web.UI.UserControl { public String Action { get; set; } public String Text { get; set; } public String CssClass { get; set; } public Boolean ShowText { get; set; } public String DisabledClass { get; set; } protected void Page_Init(object sender, EventArgs e) { DynamicHyperLink1.Action = Action; DynamicHyperLink1.Text = Text; DynamicHyperLink1.CssClass = CssClass; } /// <summary> /// Handles the PreRender event of the DynamicHyperLink1 control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e"> /// The <see cref="System.EventArgs"/> /// instance containing the event data. /// </param> protected void DynamicHyperLink1_PreRender(object sender, EventArgs e) { // the DynamicHyperLink is considered disabled if it has no URL if (String.IsNullOrEmpty(DynamicHyperLink1.NavigateUrl)) { DynamicHyperLink1.Visible = false; Literal1.Visible = false; if (ShowText) { Literal1.Visible = true; Literal1.Text = String.Format( "<span class=\"{0}\">{1}</span> ", DisabledClass, Text); } } } }
Listing 2 - DynamicHyperLink.ascx.cs
With the DynamicHyperLink web user control we simply have some properties to allow us to pass in the main properties of the asp:DynamicHyperLink Action, Text and CssClass. The last two properties ShowText and DisbledClass are used:
- ShowText – to show the Text property in a span when the DynamicHyerLink is hidden.
- DisbledClass – is the css class to use when ShowText is true.
So this is the way it works:
When the DynamicHyperLink’s NavigateUrl is and empty string or null then the DynamicHyperLink is in the disabled state. In the disabled state if ShowText is false then no control is displayed when in a disabled state, and when ShowText is true as span is displayed surrounding the Text property and having the DisabledCalss css as the span’s class.
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="DeleteLink.ascx.cs" Inherits="DD_EF_SecuringDynamicData.DeleteLink" %> <asp:LinkButton ID="LinkButton1" runat="server" CommandName="Delete" Text="Delete" OnClientClick='return confirm("Are you sure you want to delete this item?");' /> <asp:Literal ID="Literal1" runat="server"> </asp:Literal>
Listing 3 – DeleteHyperLink.ascx
public partial class DeleteHyperLink : System.Web.UI.UserControl { public Boolean ShowText { get; set; } public String CssClass { get; set; } public String DisabledClass { get; set; } protected void Page_Load(object sender, EventArgs e) { LinkButton1.CssClass = CssClass; // get restrictions for the current // users access to this table var table = DynamicDataRouteHandler.GetRequestMetaTable(Context); var usersRoles = Roles.GetRolesForUser(); var tableRestrictions = table.Attributes.OfType<SecureTableAttribute>(); if (tableRestrictions.Count() == 0) return; foreach (var tp in tableRestrictions) { // the LinkButton is considered disabled if delete is denied. if (tp.HasAnyRole(usersRoles) && (tp.Restriction & TableDeny.Delete) == TableDeny.Delete) { LinkButton1.Visible = false; LinkButton1.OnClientClick = null; LinkButton1.Enabled = false; Literal1.Visible = false; if (ShowText) { Literal1.Visible = true; Literal1.Text = String.Format(
"<span class=\"{0}\">Delete</span> ",
DisabledClass); } } } } }
Listing 4 – DeleteHyperLink.ascx.cs
This is pretty similar to the DynamicHyperLink.ascx the main difference being how the LinkButton is determined to be disabled, this is done by the foreach loop checking each restriction on the current table and checking to see if it is TableDeny.Delete and if so setting the disabled state.
Download
Happy coding
19 comments:
Missing Text....
It seems that something misses in the text, being the securecolumattribute class.
The corresponding file is in the download, but not in the explanation.
Please add the class and corresponding explanation.
Question?
In the Dynamic Data Preview 4 there is a Futures Sample, containing custom classes, tables etc.
These CustomMetaModel, CustomMetaTable (etc.) classes are more elaborate then their SecureMeta* counterparts, as they are proposed by you.
This is somewhat confusing, in different ways.
First of all, seems to me that inclusion of CustomMeta* classes should be desirable and that the reference to the Meta* classes in the SecureMeta* classes should be changed to CustomMeta*.
Not sure though, which changes are adequate. Any suggestions?
Second, the CustomMeta* classes are more elaborate and contain more definitions.
I suppose they can be simply copied (with minor alterations) to the SecureMeta*.
Any suggestions?
Third and most important: it seems to me that we want customization with security (with security being part of customization).
It then seems to be desirable to have SecureMeta* classes that extend the CustomMeta* classes.
If i am not mistaken, this would be a solution to the second point and requiring a step as mentioned in the first point.
But confusion exists: can you have a look and add a part 4 of securing dynamic data?
Thanx in advance.....
Hi trialotm, first I think you will find the missing bit in part 1.
second, this is just an example and I like to keep them as simple as possible.
And yes you are correct about the custom meta classes inheritance would let you do that.
There is more you can do with the custom metadata classes, one thing I'm looking at is allowing you to pass in a delegate for row generation. I have also asked that some of the other methods of Table and Column be made virtual so they can be extended i.e. IsReadOnly which could add the logic to determin by security if the column was read only.
Steve :D
I am not sure what you want to achieve with the extension part of your answer.
If I am not mistaken, you want a gridview or formview (the ones used in DynData) that has the attribute IsReadOnly in both the parent control (e.g. asp:gridview/formview) as the child controls (in this case, only itemtemplates or variants of that).
If that is your intention, than you have the problem that this intervenes with the DefaultMode in the formview.
Simple managed code can be used to make formviews read-only for specific (security) roles. No need to extend or no need to use attributes there.
The gridview is something different though. No attribute such as DefaultMode is present.
Then again, you probably want to prevent (based upon security rules and roles) the edit, delete and insert hyperlink and the possibility for inline editing.
Managed code can again be used to disenable and remove visibility of the linkbuttons.
The only thing that then remains is the read-only property for specific columns, but that can be easily achieved by managed code (when using templates for the columns).
Seems to me that you desire an extension that is not directly necessary. I can be mistaken.
As a final consideration: is the securityattribute meaningful, taking into consideration that everything can be achieved by managed code?
Yes, it is, as a general method. The managed code approach should be used for custom page templates or in addition, in order to tie up and intensify security.
Furthermore, the security part of dynamicdata contains the delicious routehandler, also resulting in a better security.
In short, no need for the read-only extension.
By the way, any quick idea how the prettydynamicdataroute compares to the secure dynamicdataroutehandler?
I presume the same idea applies as in my previous post.....
As a final point: if you want me to, i am happy to provide you with some (untested) code, containing the combination of security and custom classes, including the prettydynamicdataroute and securedynamicdataroutehandler.....
Euhm, as another comment.....i have changed the secure dynamicdataroute classes to incorporate both the restrictions on tables as on actions.
Maybe you can have a look at it and post the corresponding changes to this topic.
Shall i mail ?
Hi Trialot, as I explained before I'm just trying to give a simple sample that does security, I don;t waht to make to too complicated otherwise it will confuse the issue.
However if the IsReadOnly method of the Column class becomes virtual the I can return true in cases where there is restricted access this would then simplyfy the code. and when this change appears then I will look at extending the solution to incorporate it.
Steve :D
P.S. just drop me an e-mail is you want to chat more in depth on this and I can add you to messenger :D
Great stuff, but its's hard following along for us lowley VB types..
it's not the regular loops and logic that stumps us, but the multitude of new declarations with inheritance, metadata, etc..
do you know if this was translated to VB by anyone ?
Sorry about that, I switched to C# about 4-5 years ago and find it hard to switch back now :(
and I've not heard of anyone doing a port.
Steve :)
Hi Steve
I managed to understand and get everything to work except for the final two hyperlink controls (DynamicHyperLink.ascx & DeleteHyperLink.ascx). Please could you provide an example of how to use them?
Many thanks, Simon
Have you run the sample?
Thanks for the snappy response Steve.
I've been using the sample as a reference and to fill in some of the gaps. Especially the SecureColumnAttribute code. Problem is that the hyperlink controls don't appear to be implemented in the sample and I can't figure out how they are supposed to be used.
Everything else works great.
Thanks, Simon
Thanks for the snappy response Steve.
I've been using the sample as a reference and to fill in some of the gaps. Especially the SecureColumnAttribute code. Problem is that the hyperlink controls don't appear to be implemented in the sample and I can't figure out how they are supposed to be used.
Everything else works great.
Thanks, Simon
Hi Steve
The hyperlink controls don't appear to be implemented in the sample. If they are I can't find them.
Thanks, Simon
Hi Steve
The hyperlink controls don't appear to be implemented in the sample. If they are I can't find them.
Thanks, Simon
Hi Stev,
I'm new in programing ASP.NET
I use DD whith EF NET 4, I downloaded SecuringDynamicData - 2010-06-13a.zip security works without problem, but as I try to use ListDetail.aspx it does not work, the only change is that :
routes.Add(New DynamicDataRoute("{table}/ListDetails.aspx") With { _
.Action = PageAction.List, _
.RouteHandler = New SecureDynamicDataRouteHandler(), _
.Model = DefaultModel, _
.ViewName = "ListDetails"})
routes.Add(New DynamicDataRoute("{table}/ListDetails.aspx") With { _
.Action = PageAction.Details, _
.RouteHandler = New SecureDynamicDataRouteHandler(), _
.Model = DefaultModel, _
.ViewName = "ListDetails"})
Sorry the code is in VB.
Thank you for your help.
Hi VB not a problem :) I don't believe I tested it with ListDetails sorry. I'll try to have a look today.
Steve.
Thank you Steve
Hi Steve,
have you tested the "SecuringDynamicData" whith listDetails ?
nevermind about my previous question.
Post a Comment