sitemap shortcoming - asp.net

I am constrained to using a SiteMap for authentication. I am an experienced developer that has not had to use the SiteMap previously, so I am probably missing something due to the paradigm shift.
in order to get around the url limitation in SiteMap, I <doh!>cleverly</doh!> appended a querystring value:
<siteMapNode url="workflow.aspx?Location=Process1" description="Process1">
<siteMapNode url="workflow.aspx?Location=Process2" description="Process2">
the page dynamically returns the appropriate information/display based on the querystring value, and I don't have multiple stub pages. everything worked and it seemed like a good idea, until...
managers now want to access the page and edit their employee's work aliased as them, so they need to click a link like this:
href=workflow.aspx?Location=Process1&UserID=12&IDWorkflowLocation=3340
{update to explanation}
it arrives at the page correctly, but
SiteMap.CurrentNode==null;
because there is already a querystring in the sitemap it doesn't append correctly. I reaally don't want to have to make uniquely named stub .aspx pages. any ideas?

Try this:
href=workflow.aspx?Location=Process1&UserID=12&IDWorkflowLocation=3340

Have you tried programmatically modifying the site map nodes at runtime? This article explains how: http://msdn.microsoft.com/en-us/library/ms178425.aspx
I have used this in the past, but I seem to remember that the SiteMapResolve event fires on every request (even if you define it on a specific WebForm).
Hope this helps.

You need to extend the SiteMap class, override the CurrentNode property and get some of your own logic in there to catch this.

Related

Preventing users from skipping pages in an ASP.NET form

I have a data entry form that I've broken apart into 5 pages and I want to make sure that the users go through the pages in the proper order each time. The navigation is set up to take them through it properly, including a breadcrumb to go back and change previous pages. I want to make sure, however, that they don't get to a later page without going through the earlier pages first (i.e., go through pages A and B then skip to D by entering the URL directly, or start out on D using a bookmark).
I've made some attempts to prevent this, with my latest one being this, which checks for required session variables specific to each page:
public static string CheckForPageSkipping()
{
var redirectTo = "";
if (HttpContext.Current.Session["TestDate"] == null) redirectTo = "~/Auth/SignOff.aspx";
if (HttpContext.Current.Session["Repairs"] == null) redirectTo = "~/Auth/RepairNotes.aspx";
if (HttpContext.Current.Session["MeterNum"] == null) redirectTo = "~/Auth/TestResults.aspx";
if (HttpContext.Current.Session["PremiseOwner"] == null) redirectTo = "~/Auth/PremiseInfo.aspx";
return redirectTo;
}
I called this during each Page_Load event and redirected to the page it returned if it was not the page they were on. This almost worked, until I realized that it prevents you from being able to navigate backwards (it always sends you back to the latest page you haven't completed). I'm sure I can cobble something together to make this work, but I wanted to see if there is a better way to do it. Something either built in to ASP.NET, or something more elegant that someone had built in the past.
My search attempts, both in Google and on StackOverflow, yielded no useful results. Maybe I was using the wrong terms, but it was mostly stuff like I've written here (the suggestions made at the top now have not been helpful either).
It seems like you have control of the pages so why not get rid of them and put the code into user controls, register these controls in one page in panels or placeholders and control the visibility of these panels in the code so that you can properly enforce the order in which these are visited?
Have you looked at the <asp:wizard> built-in control? I think it will fit your needs and you can configure it for many different scenarios.
Here is a link describing its use: http://msdn.microsoft.com/en-us/magazine/cc163894.aspx
Also see the current official documentation: MSDN Library
There is a good pattern explained here for using multi-part forms using panels.
Multi-Part Form using Panels
If you don't want to use the Wizard control and you don't want to use Panels, either Server.Transfer or Cross Page Posting should work. With either method, checking the PreviousPage should cover your page skipping concerns.
Server.Transfer has the URL oddity you mentioned, but is otherwise pretty straightforward.
Cross-Page Posting is quite appropriately tailored to your needs as well.
Post each form to the next form page.
Receive and process the data there (with strong typing if you set it
up correctly).
Only load the new page if everything checks out (PreviousPage is
correct, data is valid).
I admit, I don't have direct experience using either of these methods myself, but I can see how they could be implemented to handle your situation.

Redirect to handling page

On the masterpage I have menu items links that look like like:
<ul><li><a href=type=article&articleId=82>Article 82</a></li></ul>
When the link is clicked, I want to navigate to the right aspx page based on the QueryString 'type' (in this case DisplayArticle.aspx) and pass the parameter to it (in this case articleId=82).
How to do it?
Should I create a special Handler page like HandleRequest.aspx, so the menu item would look like:
<ul><li><a href=HandleRequest.aspx?type=article&articleId=82>Article 82</a></li></ul>
And then after parsing the QueryString, rediret to a needed page?
Or maybe there is a better approach?
If you can't put in the direct link, use a generic handler (HandleRequest.ashx) and parse your querystrings, yo can then re-use this across your application.
If you are using asp.net MVC, you can use the URL Routing to do something similar which would be cleaner as well.
Good luck

Output caching a page except a user control in it

I have a page which contains a user control. The structure of the page is as shown below:
Incase your not able to see the above image, please check it at http://i54.tinypic.com/2r4id5f.jpg Now, apart from the contents of the UserControl, I'd like to cache the entire page. I tried using the OutputCache attribute in the .aspx page, however it caches the contents of the UserControl as well.
Kindly let me know how will I be able to cache the contents of the page except that of the user control.
Thanks in advance.
I think you can use the asp.net Substitution control to achieve this. Here is a link to ScottGu walking through an example.
The basic idea is that you cache you whole page as per usual, but mark parts for substitution that can be replaced for each request.
I think you are looking for VaryByControl. Also check out this post on fragment caching
Look at using substitutions.
This should help
However, the snag is, since substitution is done outside of the Page lifecycle, you can't render a user control for your substitution. You have to write a method that returns a string for the substitution. But this may work for you.
Have you tried adding the #OutputCache to both the usercontrol and the page but the usercontrol set the varyByParam="qsvalue;postvalue" where qsvalue is a generated query string you make random for every call of the page and postvalue is the same for postback.
The user control will still get cached, but in theory it should never get a chache hit as the qsvalue/postvalue is always different from that cached. It may not scale well - best set duration to the minimum as well, to prevent large numbers of them building up in the cache.

Why is Request.QueryString readonly?

I thought you couldn't change the QueryString on the server without a redirect.
But this code works* for me:
Request.QueryString edit
I'm so amazed.
So here are my questions regarding this:
Why is Request.QueryString readonly?
Why does this code/hack work*?
How safe is it, if you change to readonly as soon as you are done editing, both regarding bad errors or unexpected behaviour, and regarding maintaining and understanding the code?
Where in the event cycle would it make most sense to do this crazy edit if you are only using PageLoad and OnPageRender?
*More details:
I have a page with items that are grouped into tabs. Each tab is an asp:LinkButton
I want to be able to link directly to a specific tab. I do that with a QueryString parameter 'tab=tabName'. It works. But when I then click a new tab, the querystring is still in the Url, and thus the tab specified in the Querystring gets activated and not the one I clicked.
By using Request.QueryString edit this does not happen. Then my solution 'works'.
Thanks in advance.
Well the QueryString property is readonly because it cannot be changed on a single request. Obviously the browser sends only one request with only one string so only one collection is created. The hack uses reflection (i.e. manipulates the code and the memory) to change stuff that you cannot change normally. This hack breaks the encapsulation and the design of the QueryString property. You should not use it. It makes no sense from design standpoint. Your query DOES NOT change so why change the object that represents it? Only the browser can send new query string so you are basically lying to your own code about what the browser sent.
If you want the tabs to use the URL just use Hyperlinks instead of LinkButton.
From what I remember reading, this is a security standard that all browsers adhere to. It's main purpose is to stop phishing attacks, where someone could have the website www.MyLameWarcraftPhishingSite.com" and when someone hits the page, rewrite the url to look like www.blizzard.com. The only way to get to that url is to actually redirect to it.
mmm, last post was in Feb 11 - hope its ok to post in this.

How can I link to a page that only exists with a postback?

I am trying to link to a third-party site. On that site is a list of links, and I need to be able to link my site to destination of one of those. The problem is that the links are not going to URLs, they're using ASP.NET postbacks to display the description of each item in the list.
Here is the URL where the list is. I want to be able to link to specific entries in this list.
https://www.license.state.tx.us/ContinuingEducation/ContinuingEducationProvider.aspx?ProviderType=750
Check for IsPostBack in the Page_Load, otherwise perform a Response.Redirect possibly? (If I'm understanding you correctly)
EDIT
Actually, it sounds like you want to link to a page that was generated on the value of a postback. I'm not sure you can, unless you have access to the page's code. You may try simulating the GET variables and see if the page generates the same content, otherwise it's however the author coded the page and what conditions need to be met to generate the "postback content(s)".

Resources