问题
I have a user control that contains a GridView. The GridView has both a HyperLinkField column and a template column that contains a HyperLink control.
The ASP.NET project is structured as follows, with the Default.aspx page in each case using the user control.
- Application Root
- Controls
- UserControl with GridView
- SystemAdminFolder
- Default.aspx
- Edit.aspx
- OrganisationAdminFolder
- Default.aspx
- Edit.aspx
- StandardUserFolder
- Default.aspx
- Edit.aspx
- Controls
Note: The folders are being used to ensure the user has the correct role.
I need to be able to set the DataNavigateUrlFormatString for the HyperLinkField and the NavigateUrl for the HyperLink to resolve to the Edit.aspx page in the corresponding folder.
If I set the navigate URL to "Edit.aspx" the URL in the browser appears as 'http://Application Root/Controls/Edit.aspx' regardless of the originating directory.
I can't use the Web application root operator (~/) as the path needs to be relative to the current page, not the application root.
How can I use the same user control in multiple folders and resolve the URL to another page in the same folder?
Note: The question is strongly based off a similar question by azhar2000s on the asp.net forums that matches my problem.
回答1:
While typing up this question I came across one possible solution and have further modified this using feedback from @Thomas.
Changing Control.AppRelativeTemplateSourceDirectory alters the relative paths produced by the control. I've set it to a root relative virtual path for the current requests folder. Now any relative paths in the UserControl with be relative to the requested page rather than the user controls path.
//Page Load Event for the User Control
protected void Page_Load(object sender, EventArgs e)
{
string rootPath = HttpContext.Current.Request.ApplicationPath;
if (!rootPath.EndsWith("/"))
{
rootPath += "/";
}
Uri requestUri = HttpContext.Current.Request.Url;
string folderPath = requestUri.AbsolutePath.Remove(0, rootPath.Length);
string lastSegment = requestUri.Segments[requestUri.Segments.Length - 1];
folderPath = folderPath.Remove(folderPath.LastIndexOf(lastSegment));
AppRelativeTemplateSourceDirectory = "~/" + folderPath;
}
回答2:
I would set it in the Load event of the grid or the page like so:
var hyperlinkColumn = this.GridView1.Columns[0] as HyperLinkColumn;
hyperlinkColumn.DataNavigateUrlFormatString = "~/SystemAdminFolder/{0}";
This structure presumes that the Url should be different per row based on the DataNavigateUrlField
. If it should be the same url for all rows, then you can just set the NavigateUrl
property at Load. Obviously, you would set a different folder based on the user's role.
ADDITION Given what you have mentioned in your problem in comments, what I suggest is storing the Role-Folder relationship somewhere. You have a number of choices:
Simply store magically named keys in appSettings (Role_SystemAdministrators, Role_OrganizationAdministrators, etc.) with the name of the folder to which they should be directed. The advantage of this approach is that it is simple. The disadvantage is that the data must entered properly, there is nothing to stop someone from accidentally mapping a role to two folders and when a role is added it must be updated in one more place.
Create a custom ConfigSection to store the relationship. The advantage is that you can ensure that each role is only listed once. The disadvantage is that it is extra code you have to write and when a role is added you still have to add something in another place.
Read the
location
tags out of the config file. The advantage is that you can avoid having to write a value in more than one place. The disadvantage is that doing this will be a chore. You'd have to find the first tag associated with the given folder on which the current user was given permission.Read the values out of the database. The advantage is that you can easily write a management screen to update the values. The disadvantage is when a role is added you need to add something to a completely different location of the application.
You would still set folder permissions as you are doing now. However, once you have this relationship stored, you can redirect the person to the appropriate folder without having write custom forking code.
来源:https://stackoverflow.com/questions/2604636/relative-path-from-an-asp-net-user-control-navigateurl