Search Results

Search found 72 results on 3 pages for 'phill'.

Page 3/3 | < Previous Page | 1 2 3 

  • Why am I getting a new session ID on every page fetch in my Perl WWW::Mechanize script?

    - by Phill Pafford
    So I'm scraping a site that I have access to via HTTPS, I can login and start the process but each time I hit a new page (URL) the cookie Session Id changes. How do I keep the logged in Cookie Session Id? #!/usr/bin/perl -w use strict; use warnings; use WWW::Mechanize; use HTTP::Cookies; use LWP::Debug qw(+); use HTTP::Request; use LWP::UserAgent; use HTTP::Request::Common; my $un = 'username'; my $pw = 'password'; my $url = 'https://subdomain.url.com/index.do'; my $agent = WWW::Mechanize->new(cookie_jar => {}, autocheck => 0); $agent->{onerror}=\&WWW::Mechanize::_warn; $agent->agent('Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.3) Gecko/20100407 Ubuntu/9.10 (karmic) Firefox/3.6.3'); $agent->get($url); $agent->form_name('form'); $agent->field(username => $un); $agent->field(password => $pw); $agent->click("Log In"); print "After Login Cookie: "; print $agent->cookie_jar->as_string(); print "\n\n"; my $searchURL='https://subdomain.url.com/search.do'; $agent->get($searchURL); print "After Search Cookie: "; print $agent->cookie_jar->as_string(); print "\n"; The output: After Login Cookie: Set-Cookie3: JSESSIONID=367C6D; path="/thepath"; domain=subdomina.url.com; path_spec; secure; discard; version=0 After Search Cookie: Set-Cookie3: JSESSIONID=855402; path="/thepath"; domain=subdomain.com.com; path_spec; secure; discard; version=0 Also I think the site requires a CERT (Well in the browser it does), would this be the correct way to add it? $ENV{HTTPS_CERT_FILE} = 'SUBDOMAIN.URL.COM'; ## Insert this after the use HTTP::Request... Also for the CERT In using the first option in this list, is this correct? X.509 Certificate (PEM) X.509 Certificate with chain (PEM) X.509 Certificate (DER) X.509 Certificate (PKCS#7) X.509 Certificate with chain (PKCS#7)

    Read the article

  • visusal studio embedded crystal report keeps prompting database login?

    - by phill
    I'm using visual studio 2005 to develop a form with a combobox passing a value into the parameter of an embedded crystal report. I'm trying to figure out why it keeps prompting me for a database login every single time you try to run the report with a different combobox selection. Here is my code: private Sub Form1_load... Dim ConnName As String Dim ServerName As String Dim DBName As String Dim user As String Dim pass As String Dim gDBA As ADODB.Connection Dim records As ADODB.Recordset Dim datver As ADODB.Recordset Dim query As String '---OPEN THE DATABASE CONNECTIONS gDBA = New ADODB.Connection ': gDBA.CursorLocation = adUseServer 'Added to prevent time out error gDBA.CommandTimeout = 1000 : gDBA.ConnectionTimeout = 1000 gDBA.ConnectionString = "Server=svr13;Database=subscribers;User ID=KViews;Password=Solution;Trusted_Connection=True;" gDBA.Open("Data Source=Kaseya;Initial Catalog=subscribers;User Id=KViews;Password=Solution;", "KViews", "Solution") records = New ADODB.Recordset query = "select distinct groupname from _v_k order by groupname desc" 'records.ActiveConnection = gDBA.ConnectionString records.CursorType = CursorTypeEnum.adOpenForwardOnly records.LockType = LockTypeEnum.adLockReadOnly records.Open(query, gDBA) Do While Not records.EOF ComboBox1.Items.Add(records.Fields("groupname").Value) records.MoveNext() Loop end Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim selected As String selected = ComboBox1.Text Dim cryRpt As New ReportDocument cryRpt.Load("C:\Visual Studio 2005\Projects\WindowsApplication1\WindowsApplication1\CrystalReport1.rpt") cryRpt.SetDatabaseLogon("KViews", "Solutions", "svr13", "subscribers") cryRpt.SetParameterValue("companyname", selected) CrystalReportViewer1.ReportSource = cryRpt CrystalReportViewer1.Refresh() End Sub I looked at this previous posting http://stackoverflow.com/questions/1132314/database-login-prompt-with-crystal-reports but this wasn't very helpful. I couldn't find where a CMC was to disable the prompt. Any ideas? thanks in advance

    Read the article

  • php : is this if condition correct?

    - by phill
    I have the following if condition statement if ( (strlen($data[70])>0) || ( (remove19((trim($data[29])) == '7135556666')) && isLongDistance($data[8])) ) where $data is a recordset from a database. My goal is to include all rows where $data[70] isn't blank, and also include rows where $data[29] = 713555666 && $data[8] isLongDistance = TRUE My question is, if isLongDistance($data[8]) returns false, will it still return the row since $data[70] is not blank? thanks in advance

    Read the article

  • Perl latin-9? Unicode - need to add support

    - by Phill Pafford
    I have an application that is being expanded to the UK and I will need to add support for Latin-9 Unicode. I have done some Googling but found nothing solid as to what is involved in the process. Any tips? Here is some code (Just the bits for Unicode stuff) use Unicode::String qw(utf8 latin1 utf16); # How to call $encoded_txt = $self->unicode_encode($item->{value}); # Function part sub unicode_encode { shift() if ref($_[0]); my $toencode = shift(); return undef unless defined($toencode); Unicode::String->stringify_as("utf8"); my $unicode_str = Unicode::String->new(); # encode Perl UTF-8 string into latin1 Unicode::String # - currently only Basic Latin and Latin 1 Supplement # are supported here due to issues with Unicode::String . $unicode_str->latin1( $toencode ); ... Any help would be great and thanks.

    Read the article

  • Java Servlet connecting to SQL Server tutorial?

    - by phill
    Can anyone recommend a tutorial on how to write a Java Servlet which connects to MS SQL server and manages data? I'm trying to write something which pulls products out of one database and inserts them into a stored procedure located on another database. Thanks in advance.

    Read the article

  • Why am I getting an error when return TRUE/FALSE to type Boolean?

    - by phill
    I wrote the following code: import java.lang.*; import DB.*; private Boolean validateInvoice(String i) { int count = 0; try { //check how many rowsets ResultSet c = connection.DBquery("select count(*) from Invce i,cust c where tranid like '"+i+"' and i.key = c.key "); while (c.next()) { System.out.println("rowcount : " + c.getInt(1)); count = c.getInt(1); } if (count > 0 ) { return TRUE; } else { return FALSE; } //end if } catch(Exception e){e.printStackTrace();return FALSE;} } The errors I'm getting are: i.java:195: cannot find symbol symbol : variable TRUE location: class changei.iTable return TRUE; i.java:197: cannot find symbol symbol : variable TRUE location: class changei.iTable return FALSE; i.java:201:: cannot find symbol symbol : variable FALSE location: class changei.iTable catch(Exception e){e.printStackTrace();return FALSE;} The Connection class comes from the DB package i created. Is the return TRUE/FALSE correct since the function is a Boolean return type?

    Read the article

  • vb6 ADODB TSQL procedure call quit working after database migration

    - by phill
    This code was once working on sql server 2005. Now isolated in a visual basic 6 sub routine using ADODB to connect to a sql server 2008 database it throws an error saying: "Login failed for user 'admin' " I have since verified the connection string does work if i replace the body of this sub with the alternative code below this sub. When I run the small program with the button, it stops where it is marked below the asterisk line. Any ideas? thanks in advance. Private Sub Command1_Click() Dim cSQLConn As New ADODB.Connection Dim cmdGetInvoices As New ADODB.Command Dim myRs As New ADODB.Recordset Dim dStartDateIn As Date dStartDateIn = "2010/05/01" cSQLConn.ConnectionString = "Provider=sqloledb;" _ & "SERVER=NET-BRAIN;" _ & "Database=DB_app;" _ & "User Id=admin;" _ & "Password=mudslinger;" cSQLConn.Open cmdGetInvoices.CommandTimeout = 0 sProc = "GetUnconvertedInvoices" 'On Error GoTo GetUnconvertedInvoices_Err With cmdGetInvoices .CommandType = adCmdStoredProc .CommandText = "_sp_cwm5_GetUnCvtdInv" .Name = "_sp_cwm5_GetUnCvtdInv" Set oParm1 = .CreateParameter("@StartDate", adDate, adParamInput) .Parameters.Append oParm1 oParm1.Value = dStartDateIn .ActiveConnection = cSQLConn End With With myRs .CursorLocation = adUseClient .LockType = adLockBatchOptimistic .CursorType = adOpenKeyset '.CursorType = adOpenStatic .CacheSize = 5000 '***************************Debug stops here .Open cmdGetInvoices End With If myRs.State = adStateOpen Then Set GetUnconvertedInvoices = myRs Else Set GetUnconvertedInvoices = Nothing End If End Sub Here is the code which validates the connection string is working. Dim cSQLConn As New ADODB.Connection Dim cmdGetInvoices As New ADODB.Command Dim myRs As New ADODB.Recordset cSQLConn.ConnectionString = "Provider=sqloledb;" _ & "SERVER=NET-BRAIN;" _ & "Database=DB_app;" _ & "User Id=admin;" _ & "Password=mudslinger;" cSQLConn.Open cmdGetInvoices.CommandTimeout = 0 sProc = "GetUnconvertedInvoices" With cmdGetInvoices .ActiveConnection = cSQLConn .CommandText = "SELECT top 5 * FROM tarInvoice;" .CommandType = adCmdText End With With myRs .CursorLocation = adUseClient .LockType = adLockBatchOptimistic '.CursorType = adOpenKeyset .CursorType = adOpenStatic '.CacheSize = 5000 .Open cmdGetInvoices End With If myRs.EOF = False Then myRs.MoveFirst Do MsgBox "Record " & myRs.AbsolutePosition & " " & _ myRs.Fields(0).Name & "=" & myRs.Fields(0) & " " & _ myRs.Fields(1).Name & "=" & myRs.Fields(1) myRs.MoveNext Loop Until myRs.EOF = True End If

    Read the article

  • How can I print the cookie_jar values in Perl's WWW::Mechanize?

    - by Phill Pafford
    How can I print the values of the cookie/cookie_jar being set? Trying: ##my $cookie_jar=HTTP::Cookies->new(file => "cookie.jar",autosave=>1,ignore_discard=>1); my $cookie_jar=HTTP::Cookies->new(); ## Would like it to be in memory my $agent = WWW::Mechanize->new(cookie_jar => $cookie_jar); ##my $agent = WWW::Mechanize->new(); ##my $agent = WWW::Mechanize->new(autocheck => 1); ##$agent->cookie_jar( {} ); # we need cookies ##$agent->cookie_jar(HTTP::Cookies->new); print "Set Cookie Jar?\n"; print $agent->cookie_jar->as_string(); print "\n"; $agent->get($url); // url is a https site Not too much luck with any of these, what am I doing wrong?

    Read the article

  • VBScript: how to set values from recordset to string

    - by phill
    This is probably a beginner question, but how do you set a recordset to a string variable? Here is my code: Function getOffice (strname, uname) strEmail = uname WScript.Echo "email: " & strEmail Dim objRoot : Set objRoot = GetObject("LDAP://RootDSE") Dim objDomain : Set objDomain = GetObject("LDAP://" & objRoot.Get("defaultNamingContext")) Dim cn : Set cn = CreateObject("ADODB.Connection") Dim cmd : Set cmd = CreateObject("ADODB.Command") cn.Provider = "ADsDSOObject" cn.Open "Active Directory Provider" Set cmd.ActiveConnection = cn cmd.CommandText = "SELECT physicalDeliveryOfficeName FROM '" & objDomain.ADsPath & "' WHERE mail='" & strEmail & "'" cmd.Properties("Page Size") = 1 cmd.Properties("Timeout") = 300 cmd.Properties("Searchscope") = ADS_SCOPE_SUBTREE Dim objRS : Set objRS = cmd.Execute WScript.Echo objRS.Fields(0) Set cmd = Nothing Set cn = Nothing Set objDomain = Nothing Set objRoot = Nothing Dim arStore Set getOffice = objRS.Fields(0) Set objRS = Nothing End function When I try to run the function, it throws an error "vbscript runtime error: Type mismatch" I presume this means it can't set the string variable with a recordset value. How do I fix this problem?

    Read the article

  • vb.net : is it possible to connect to sql server 2008 via odbc but not through vb.net code?

    - by phill
    I'm supporting an old vb.net program whose database it connected to was moved from SQL Server 2005 to SQL Server 2008. Is there a setting on SQL Server 2008 which will allow ODBC connections to access the database but not allow VB.NET to connect to it programmatically? the error i keep receiving in the app is: An error has occurred while establishing a connection to the server. When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (provider: Named Pipes Provider, error: 40 – Could not open a connection to SQL Server) however I can connect to it when I create a system dsn to the sql server instance and through VS2005's Tools Connect to Database. Here is the code I'm using to connect: dim strC as string strC = "data source=bob; database=subscribers; user id=bobuser; password=passme" dim connection as New SqlClient.SqlConnection(strC) try connection.open() catch ex as Exception msgbox(ex.message) end try connection.Close()

    Read the article

  • java jsp : connecting to sql server tutorial?

    - by phill
    Can anyone recommend a tutorial on how to write a java servlet which connects to ms sql server and manages data? I'm trying to write something which pulls products out of one database and inserts them into a stored procedure located on another database. thanks in advance

    Read the article

  • .Net in HTML tp return true if reader object not null, otherwise return false

    - by Phill Healey
    I'm using a DataList to show some data from the database and populating the fields on the html side. I now have a requirement to change the visibility of a panel based on whether or not a db field has data or not. I need to be able to show the panel if the relevant data field has content, and hide it if it doesn't. Eg: <asp:Panel ID="pnlNew" runat="server" Style="margin:0; padding:0; width:42px; height:18px; bottom:5px; right:10px; float:right; position:relative; background:url(../_imgVideoBadge.png) no-repeat;" Visible='<%# Eval("cheese") != null %>' ToolTip="available"></asp:Panel> Obviously this doesn't work in terms of the visible property. But hopefully it gives an idea of what I'm trying to achieve. Any help would be greatly appreciated. I've seen examples previously of doing something along the lines of: a ?? b:c How could this be applied to the above requirement?? Thanks in advance.

    Read the article

  • Salesforce/PHP - outbound messages (SOAP) - memory limit issue? DOMDocument::loadXML() issue?

    - by Phill Pafford
    I'm using Salesforce to send outbound messages (via SOAP) to another server. The server can process about 8 messages at a time, but will not send back the ACK file if the SOAP request contains more than 8 messages. SF can send up to 100 outbound messages in 1 SOAP request and I think this is causing a memory issue with PHP. If I process the outbound messages 1 by 1 they all go through fine, I can even do 8 at a time with no issues. But larger sets are not working. ERROR in SF: org.xml.sax.SAXParseException: Premature end of file Looking in the HTTP error logs I see that the incoming SOAP message looks to be getting cut of which throws a PHP warning stating: DOMDocument::loadXML() ... Premature end of data in tag ... PHP Fatal error: Call to a member function getAttribute() on a non-object This leads me to believe that PHP is having a memory issue and can not parse the incoming message due to it's size. I was thinking I could just set: ini_set('memory_limit', '64M'); // This has done nothing to fix the problem But would this be the correct approach? Is there a way I could set this to increase with the incoming SOAP request dynamically? UPDATE: Adding some code $data = fopen('php://input','rb'); $headers = getallheaders(); $content_length = $headers['Content-Length']; $buffer_length = 1000; $fread_length = $content_length + $buffer_length; $content = fread($data,$fread_length); /** * Parse values from soap string into DOM XML */ $dom = new DOMDocument(); $dom->loadXML($content); ....

    Read the article

  • jQuery UI Calendar displays too large, would like the demo size???

    - by Phill Pafford
    So I downloaded a custom themed UI for jQuery and added the calendar control to my sight (Example: link text). In the example it shows/displays the size I would like but on my webpage it's about twice the size. why??? I do have a ton of other CSS but I don't have control over the look and feel of the page (Can't touch current CSS, MEH!!). Is there a way to get the demo look on my site? I think this is the code that jQuery UI has that might be complicating things /* Component containers ----------------------------------*/ .ui-widget { font-family: Arial, Helvetica, Verdana, sans-serif; font-size: 1.1em; } .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Arial, Helvetica, Verdana, sans-serif; font-size: 1em; } .ui-widget-content { border: 1px solid #B9C4CE; background: #ffffff url(../images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #616161; } .ui-widget-content a { color: #616161; } .ui-widget-header { border: 1px solid #467AA7; background: #467AA7 url(../images/ui-bg_highlight-soft_75_467AA7_1x100.png) 50% 50% repeat-x; color: #fff; font-weight: bold; } .ui-widget-header a { color: #fff; } It's part of the Custom UI CSS

    Read the article

  • Is it possible to auto generate Getter/Setter from Array Values in PHP?

    - by Phill Pafford
    So I have a couple of arrays $array_1 = Array('one','two','three'); $array_2 = Array('red','blue','green'); Is there a dynamic way to create the Setters and Getters for an array with single value entries? So the class would be something like: class xFromArray() { } So the above if I passed $array_1 it would generate something like this: private $one; setOne($x) { $one = $x; } getOne() { return $one; } if I passed $array_2 it would generate something like this: private $red; setRed($x) { $red = $x; } getRed() { return $red; } So I would call it somehow like this? (My best guess but doesn't seem that this would work) $xFromArray = new xFromArray; foreach($array_1 as $key=>$data) { $xFromArray->create_function(set.ucfirst($data)($data)); echo $xFromArray->create_function(get.ucfirst($data)); }

    Read the article

  • How do I get Java to use the serial port in Linux?

    - by Phillip Gibb
    We make use of a java application that manages a pinpad via the serial port. This works perfectly on windows with the Sun Comm.jar, the supplied dll and the properties file. Now we are attempting to use this solution on Linux (actually it does run on various other flavours of linux out in the field) - with Ubuntu server mode. After much attempts - blood, sweat and almost tears we have this scenario: Java version 1.4.2_17 Linux - Ubuntu Comm libs - Comm3 supplied by sun with the default driver specified An external comm test shows the comm ports: /dev/ttyS0 and /dev/ttyS1 But the java application says unable to open port /dev/ttyS1 (using the RXRT files produces invalid port errors) Has anyone been able to use java 1.4.2 on linux for serial port communication and found a solution that I could apply in my scenario? greatly appreciated Phill

    Read the article

  • How to recursively delete some xml elements using XSLT

    - by Monomachus
    Hi, So I got this situation which sucks. I have an XML like this <table border="1" cols="200 100pt 200"> <tr> <td>isbn</td> <td>title</td> <td>price</td> </tr> <tr> <td /> <td /> <td> <span type="champsimple" id="9b297fb5-d12b-46b1-8899-487a2df0104e" categorieid="a1c70692-0427-425b-983c-1a08b6585364" champcoderef="01f12b93-b4c5-401b-9da1-c9385d77e43f"> [prénom] </span> <span type="champsimple" id="e103a6a5-d1be-4c34-8a54-d234179fb4ea" categorieid="a1c70692-0427-425b-983c-1a08b6585364" champcoderef="01f12b93-b4c5-401b-9da1-c9385d77e43f">[nom]</span> <span></span> </td> </tr> <tr></tr> <tr> <td></td> <td>Phill It in</td> </tr> <tr> <table id="cas1"> <tr> <td ></td> <td >foo</td> </tr> <tr> <td >bar</td> <td >boo</td> </tr> </table> </tr> <tr> <table id="cas2"> <tr> <td ></td> <td >foo</td> </tr> <tr> <td ></td> <td >boo</td> </tr> </table> </tr> <tr> <table id="cas3"> <tr> <td >bar</td> <td ></td> </tr> <tr> <td >foo</td> <td >boo</td> </tr> </table> </tr> <tr> <table id="cas4"> <tr> <td /> <td /> </tr> <tr> <td>foo</td> <td>boo</td> </tr> </table> </tr> <table id="cas4"> <tr> <td /> <td /> </tr> <tr> <td>foo</td> <td>boo</td> </tr> </table> <tr> <td /> <td /> </tr> </table> Now the question is how would I recursively delete all empty td, tr and table elements? Now I use this XSLT <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*" /> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="td[not(node())]" /> <xsl:template match="tr[not(node())]" /> <xsl:template match="table[not(node())]" /> </xsl:stylesheet> But it doesn't do very well. After I delete td, a tr becomes empty but it doesn't handle that. Too bad. See the table element with "cas4". <table border="1" cols="200 100pt 200"> <tr> <td>isbn</td> <td>title</td> <td>price</td> </tr> <tr> <td> <span type="champsimple" id="9b297fb5-d12b-46b1-8899-487a2df0104e" categorieid="a1c70692-0427-425b-983c-1a08b6585364" champcoderef="01f12b93-b4c5-401b-9da1-c9385d77e43f"> [prénom] </span> <span type="champsimple" id="e103a6a5-d1be-4c34-8a54-d234179fb4ea" categorieid="a1c70692-0427-425b-983c-1a08b6585364" champcoderef="01f12b93-b4c5-401b-9da1-c9385d77e43f">[nom]</span> <span /> </td> </tr> <tr> <td>Phill It in</td> </tr> <tr> <table id="cas1"> <tr> <td>foo</td> </tr> <tr> <td>bar</td> <td>boo</td> </tr> </table> </tr> <tr> <table id="cas2"> <tr> <td>foo</td> </tr> <tr> <td>boo</td> </tr> </table> </tr> <tr> <table id="cas3"> <tr> <td>bar</td> </tr> <tr> <td>foo</td> <td>boo</td> </tr> </table> </tr> <tr> <table id="cas4"> <tr /> <tr> <td>foo</td> <td>boo</td> </tr> </table> </tr> <table id="cas4"> <tr /> <tr> <td>foo</td> <td>boo</td> </tr> </table> <tr /> </table> How would you solve this problem?

    Read the article

  • Custom ASP.NET Routing to an HttpHandler

    - by Rick Strahl
    As of version 4.0 ASP.NET natively supports routing via the now built-in System.Web.Routing namespace. Routing features are automatically integrated into the HtttpRuntime via a few custom interfaces. New Web Forms Routing Support In ASP.NET 4.0 there are a host of improvements including routing support baked into Web Forms via a RouteData property available on the Page class and RouteCollection.MapPageRoute() route handler that makes it easy to route to Web forms. To map ASP.NET Page routes is as simple as setting up the routes with MapPageRoute:protected void Application_Start(object sender, EventArgs e) { RegisterRoutes(RouteTable.Routes); } void RegisterRoutes(RouteCollection routes) { routes.MapPageRoute("StockQuote", "StockQuote/{symbol}", "StockQuote.aspx"); routes.MapPageRoute("StockQuotes", "StockQuotes/{symbolList}", "StockQuotes.aspx"); } and then accessing the route data in the page you can then use the new Page class RouteData property to retrieve the dynamic route data information:public partial class StockQuote1 : System.Web.UI.Page { protected StockQuote Quote = null; protected void Page_Load(object sender, EventArgs e) { string symbol = RouteData.Values["symbol"] as string; StockServer server = new StockServer(); Quote = server.GetStockQuote(symbol); // display stock data in Page View } } Simple, quick and doesn’t require much explanation. If you’re using WebForms most of your routing needs should be served just fine by this simple mechanism. Kudos to the ASP.NET team for putting this in the box and making it easy! How Routing Works To handle Routing in ASP.NET involves these steps: Registering Routes Creating a custom RouteHandler to retrieve an HttpHandler Attaching RouteData to your HttpHandler Picking up Route Information in your Request code Registering routes makes ASP.NET aware of the Routes you want to handle via the static RouteTable.Routes collection. You basically add routes to this collection to let ASP.NET know which URL patterns it should watch for. You typically hook up routes off a RegisterRoutes method that fires in Application_Start as I did in the example above to ensure routes are added only once when the application first starts up. When you create a route, you pass in a RouteHandler instance which ASP.NET caches and reuses as routes are matched. Once registered ASP.NET monitors the routes and if a match is found just prior to the HttpHandler instantiation, ASP.NET uses the RouteHandler registered for the route and calls GetHandler() on it to retrieve an HttpHandler instance. The RouteHandler.GetHandler() method is responsible for creating an instance of an HttpHandler that is to handle the request and – if necessary – to assign any additional custom data to the handler. At minimum you probably want to pass the RouteData to the handler so the handler can identify the request based on the route data available. To do this you typically add  a RouteData property to your handler and then assign the property from the RouteHandlers request context. This is essentially how Page.RouteData comes into being and this approach should work well for any custom handler implementation that requires RouteData. It’s a shame that ASP.NET doesn’t have a top level intrinsic object that’s accessible off the HttpContext object to provide route data more generically, but since RouteData is directly tied to HttpHandlers and not all handlers support it it might cause some confusion of when it’s actually available. Bottom line is that if you want to hold on to RouteData you have to assign it to a custom property of the handler or else pass it to the handler via Context.Items[] object that can be retrieved on an as needed basis. It’s important to understand that routing is hooked up via RouteHandlers that are responsible for loading HttpHandler instances. RouteHandlers are invoked for every request that matches a route and through this RouteHandler instance the Handler gains access to the current RouteData. Because of this logic it’s important to understand that Routing is really tied to HttpHandlers and not available prior to handler instantiation, which is pretty late in the HttpRuntime’s request pipeline. IOW, Routing works with Handlers but not with earlier in the pipeline within Modules. Specifically ASP.NET calls RouteHandler.GetHandler() from the PostResolveRequestCache HttpRuntime pipeline event. Here’s the call stack at the beginning of the GetHandler() call: which fires just before handler resolution. Non-Page Routing – You need to build custom RouteHandlers If you need to route to a custom Http Handler or other non-Page (and non-MVC) endpoint in the HttpRuntime, there is no generic mapping support available. You need to create a custom RouteHandler that can manage creating an instance of an HttpHandler that is fired in response to a routed request. Depending on what you are doing this process can be simple or fairly involved as your code is responsible based on the route data provided which handler to instantiate, and more importantly how to pass the route data on to the Handler. Luckily creating a RouteHandler is easy by implementing the IRouteHandler interface which has only a single GetHttpHandler(RequestContext context) method. In this method you can pick up the requestContext.RouteData, instantiate the HttpHandler of choice, and assign the RouteData to it. Then pass back the handler and you’re done.Here’s a simple example of GetHttpHandler() method that dynamically creates a handler based on a passed in Handler type./// <summary> /// Retrieves an Http Handler based on the type specified in the constructor /// </summary> /// <param name="requestContext"></param> /// <returns></returns> IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) { IHttpHandler handler = Activator.CreateInstance(CallbackHandlerType) as IHttpHandler; // If we're dealing with a Callback Handler // pass the RouteData for this route to the Handler if (handler is CallbackHandler) ((CallbackHandler)handler).RouteData = requestContext.RouteData; return handler; } Note that this code checks for a specific type of handler and if it matches assigns the RouteData to this handler. This is optional but quite a common scenario if you want to work with RouteData. If the handler you need to instantiate isn’t under your control but you still need to pass RouteData to Handler code, an alternative is to pass the RouteData via the HttpContext.Items collection:IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) { IHttpHandler handler = Activator.CreateInstance(CallbackHandlerType) as IHttpHandler; requestContext.HttpContext.Items["RouteData"] = requestContext.RouteData; return handler; } The code in the handler implementation can then pick up the RouteData from the context collection as needed:RouteData routeData = HttpContext.Current.Items["RouteData"] as RouteData This isn’t as clean as having an explicit RouteData property, but it does have the advantage that the route data is visible anywhere in the Handler’s code chain. It’s definitely preferable to create a custom property on your handler, but the Context work-around works in a pinch when you don’t’ own the handler code and have dynamic code executing as part of the handler execution. An Example of a Custom RouteHandler: Attribute Based Route Implementation In this post I’m going to discuss a custom routine implementation I built for my CallbackHandler class in the West Wind Web & Ajax Toolkit. CallbackHandler can be very easily used for creating AJAX, REST and POX requests following RPC style method mapping. You can pass parameters via URL query string, POST data or raw data structures, and you can retrieve results as JSON, XML or raw string/binary data. It’s a quick and easy way to build service interfaces with no fuss. As a quick review here’s how CallbackHandler works: You create an Http Handler that derives from CallbackHandler You implement methods that have a [CallbackMethod] Attribute and that’s it. Here’s an example of an CallbackHandler implementation in an ashx.cs based handler:// RestService.ashx.cs public class RestService : CallbackHandler { [CallbackMethod] public StockQuote GetStockQuote(string symbol) { StockServer server = new StockServer(); return server.GetStockQuote(symbol); } [CallbackMethod] public StockQuote[] GetStockQuotes(string symbolList) { StockServer server = new StockServer(); string[] symbols = symbolList.Split(new char[2] { ',',';' },StringSplitOptions.RemoveEmptyEntries); return server.GetStockQuotes(symbols); } } CallbackHandler makes it super easy to create a method on the server, pass data to it via POST, QueryString or raw JSON/XML data, and then retrieve the results easily back in various formats. This works wonderful and I’ve used these tools in many projects for myself and with clients. But one thing missing has been the ability to create clean URLs. Typical URLs looked like this: http://www.west-wind.com/WestwindWebToolkit/samples/Rest/StockService.ashx?Method=GetStockQuote&symbol=msfthttp://www.west-wind.com/WestwindWebToolkit/samples/Rest/StockService.ashx?Method=GetStockQuotes&symbolList=msft,intc,gld,slw,mwe&format=xml which works and is clear enough, but also clearly very ugly. It would be much nicer if URLs could look like this: http://www.west-wind.com//WestwindWebtoolkit/Samples/StockQuote/msfthttp://www.west-wind.com/WestwindWebtoolkit/Samples/StockQuotes/msft,intc,gld,slw?format=xml (the Virtual Root in this sample is WestWindWebToolkit/Samples and StockQuote/{symbol} is the route)(If you use FireFox try using the JSONView plug-in make it easier to view JSON content) So, taking a clue from the WCF REST tools that use RouteUrls I set out to create a way to specify RouteUrls for each of the endpoints. The change made basically allows changing the above to: [CallbackMethod(RouteUrl="RestService/StockQuote/{symbol}")] public StockQuote GetStockQuote(string symbol) { StockServer server = new StockServer(); return server.GetStockQuote(symbol); } [CallbackMethod(RouteUrl = "RestService/StockQuotes/{symbolList}")] public StockQuote[] GetStockQuotes(string symbolList) { StockServer server = new StockServer(); string[] symbols = symbolList.Split(new char[2] { ',',';' },StringSplitOptions.RemoveEmptyEntries); return server.GetStockQuotes(symbols); } where a RouteUrl is specified as part of the Callback attribute. And with the changes made with RouteUrls I can now get URLs like the second set shown earlier. So how does that work? Let’s find out… How to Create Custom Routes As mentioned earlier Routing is made up of several steps: Creating a custom RouteHandler to create HttpHandler instances Mapping the actual Routes to the RouteHandler Retrieving the RouteData and actually doing something useful with it in the HttpHandler In the CallbackHandler routing example above this works out to something like this: Create a custom RouteHandler that includes a property to track the method to call Set up the routes using Reflection against the class Looking for any RouteUrls in the CallbackMethod attribute Add a RouteData property to the CallbackHandler so we can access the RouteData in the code of the handler Creating a Custom Route Handler To make the above work I created a custom RouteHandler class that includes the actual IRouteHandler implementation as well as a generic and static method to automatically register all routes marked with the [CallbackMethod(RouteUrl="…")] attribute. Here’s the code:/// <summary> /// Route handler that can create instances of CallbackHandler derived /// callback classes. The route handler tracks the method name and /// creates an instance of the service in a predictable manner /// </summary> /// <typeparam name="TCallbackHandler">CallbackHandler type</typeparam> public class CallbackHandlerRouteHandler : IRouteHandler { /// <summary> /// Method name that is to be called on this route. /// Set by the automatically generated RegisterRoutes /// invokation. /// </summary> public string MethodName { get; set; } /// <summary> /// The type of the handler we're going to instantiate. /// Needed so we can semi-generically instantiate the /// handler and call the method on it. /// </summary> public Type CallbackHandlerType { get; set; } /// <summary> /// Constructor to pass in the two required components we /// need to create an instance of our handler. /// </summary> /// <param name="methodName"></param> /// <param name="callbackHandlerType"></param> public CallbackHandlerRouteHandler(string methodName, Type callbackHandlerType) { MethodName = methodName; CallbackHandlerType = callbackHandlerType; } /// <summary> /// Retrieves an Http Handler based on the type specified in the constructor /// </summary> /// <param name="requestContext"></param> /// <returns></returns> IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) { IHttpHandler handler = Activator.CreateInstance(CallbackHandlerType) as IHttpHandler; // If we're dealing with a Callback Handler // pass the RouteData for this route to the Handler if (handler is CallbackHandler) ((CallbackHandler)handler).RouteData = requestContext.RouteData; return handler; } /// <summary> /// Generic method to register all routes from a CallbackHandler /// that have RouteUrls defined on the [CallbackMethod] attribute /// </summary> /// <typeparam name="TCallbackHandler">CallbackHandler Type</typeparam> /// <param name="routes"></param> public static void RegisterRoutes<TCallbackHandler>(RouteCollection routes) { // find all methods var methods = typeof(TCallbackHandler).GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (var method in methods) { var attrs = method.GetCustomAttributes(typeof(CallbackMethodAttribute), false); if (attrs.Length < 1) continue; CallbackMethodAttribute attr = attrs[0] as CallbackMethodAttribute; if (string.IsNullOrEmpty(attr.RouteUrl)) continue; // Add the route routes.Add(method.Name, new Route(attr.RouteUrl, new CallbackHandlerRouteHandler(method.Name, typeof(TCallbackHandler)))); } } } The RouteHandler implements IRouteHandler, and its responsibility via the GetHandler method is to create an HttpHandler based on the route data. When ASP.NET calls GetHandler it passes a requestContext parameter which includes a requestContext.RouteData property. This parameter holds the current request’s route data as well as an instance of the current RouteHandler. If you look at GetHttpHandler() you can see that the code creates an instance of the handler we are interested in and then sets the RouteData property on the handler. This is how you can pass the current request’s RouteData to the handler. The RouteData object also has a  RouteData.RouteHandler property that is also available to the Handler later, which is useful in order to get additional information about the current route. In our case here the RouteHandler includes a MethodName property that identifies the method to execute in the handler since that value no longer comes from the URL so we need to figure out the method name some other way. The method name is mapped explicitly when the RouteHandler is created and here the static method that auto-registers all CallbackMethods with RouteUrls sets the method name when it creates the routes while reflecting over the methods (more on this in a minute). The important point here is that you can attach additional properties to the RouteHandler and you can then later access the RouteHandler and its properties later in the Handler to pick up these custom values. This is a crucial feature in that the RouteHandler serves in passing additional context to the handler so it knows what actions to perform. The automatic route registration is handled by the static RegisterRoutes<TCallbackHandler> method. This method is generic and totally reusable for any CallbackHandler type handler. To register a CallbackHandler and any RouteUrls it has defined you simple use code like this in Application_Start (or other application startup code):protected void Application_Start(object sender, EventArgs e) { // Register Routes for RestService CallbackHandlerRouteHandler.RegisterRoutes<RestService>(RouteTable.Routes); } If you have multiple CallbackHandler style services you can make multiple calls to RegisterRoutes for each of the service types. RegisterRoutes internally uses reflection to run through all the methods of the Handler, looking for CallbackMethod attributes and whether a RouteUrl is specified. If it is a new instance of a CallbackHandlerRouteHandler is created and the name of the method and the type are set. routes.Add(method.Name,           new Route(attr.RouteUrl, new CallbackHandlerRouteHandler(method.Name, typeof(TCallbackHandler) )) ); While the routing with CallbackHandlerRouteHandler is set up automatically for all methods that use the RouteUrl attribute, you can also use code to hook up those routes manually and skip using the attribute. The code for this is straightforward and just requires that you manually map each individual route to each method you want a routed: protected void Application_Start(objectsender, EventArgs e){    RegisterRoutes(RouteTable.Routes);}void RegisterRoutes(RouteCollection routes) { routes.Add("StockQuote Route",new Route("StockQuote/{symbol}",                     new CallbackHandlerRouteHandler("GetStockQuote",typeof(RestService) ) ) );     routes.Add("StockQuotes Route",new Route("StockQuotes/{symbolList}",                     new CallbackHandlerRouteHandler("GetStockQuotes",typeof(RestService) ) ) );}I think it’s clearly easier to have CallbackHandlerRouteHandler.RegisterRoutes() do this automatically for you based on RouteUrl attributes, but some people have a real aversion to attaching logic via attributes. Just realize that the option to manually create your routes is available as well. Using the RouteData in the Handler A RouteHandler’s responsibility is to create an HttpHandler and as mentioned earlier, natively IHttpHandler doesn’t have any support for RouteData. In order to utilize RouteData in your handler code you have to pass the RouteData to the handler. In my CallbackHandlerRouteHandler when it creates the HttpHandler instance it creates the instance and then assigns the custom RouteData property on the handler:IHttpHandler handler = Activator.CreateInstance(CallbackHandlerType) as IHttpHandler; if (handler is CallbackHandler) ((CallbackHandler)handler).RouteData = requestContext.RouteData; return handler; Again this only works if you actually add a RouteData property to your handler explicitly as I did in my CallbackHandler implementation:/// <summary> /// Optionally store RouteData on this handler /// so we can access it internally /// </summary> public RouteData RouteData {get; set; } and the RouteHandler needs to set it when it creates the handler instance. Once you have the route data in your handler you can access Route Keys and Values and also the RouteHandler. Since my RouteHandler has a custom property for the MethodName to retrieve it from within the handler I can do something like this now to retrieve the MethodName (this example is actually not in the handler but target is an instance pass to the processor): // check for Route Data method name if (target is CallbackHandler) { var routeData = ((CallbackHandler)target).RouteData; if (routeData != null) methodToCall = ((CallbackHandlerRouteHandler)routeData.RouteHandler).MethodName; } When I need to access the dynamic values in the route ( symbol in StockQuote/{symbol}) I can retrieve it easily with the Values collection (RouteData.Values["symbol"]). In my CallbackHandler processing logic I’m basically looking for matching parameter names to Route parameters: // look for parameters in the routeif(routeData != null){    string parmString = routeData.Values[parameter.Name] as string;    adjustedParms[parmCounter] = ReflectionUtils.StringToTypedValue(parmString, parameter.ParameterType);} And with that we’ve come full circle. We’ve created a custom RouteHandler() that passes the RouteData to the handler it creates. We’ve registered our routes to use the RouteHandler, and we’ve utilized the route data in our handler. For completeness sake here’s the routine that executes a method call based on the parameters passed in and one of the options is to retrieve the inbound parameters off RouteData (as well as from POST data or QueryString parameters):internal object ExecuteMethod(string method, object target, string[] parameters, CallbackMethodParameterType paramType, ref CallbackMethodAttribute callbackMethodAttribute) { HttpRequest Request = HttpContext.Current.Request; object Result = null; // Stores parsed parameters (from string JSON or QUeryString Values) object[] adjustedParms = null; Type PageType = target.GetType(); MethodInfo MI = PageType.GetMethod(method, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (MI == null) throw new InvalidOperationException("Invalid Server Method."); object[] methods = MI.GetCustomAttributes(typeof(CallbackMethodAttribute), false); if (methods.Length < 1) throw new InvalidOperationException("Server method is not accessible due to missing CallbackMethod attribute"); if (callbackMethodAttribute != null) callbackMethodAttribute = methods[0] as CallbackMethodAttribute; ParameterInfo[] parms = MI.GetParameters(); JSONSerializer serializer = new JSONSerializer(); RouteData routeData = null; if (target is CallbackHandler) routeData = ((CallbackHandler)target).RouteData; int parmCounter = 0; adjustedParms = new object[parms.Length]; foreach (ParameterInfo parameter in parms) { // Retrieve parameters out of QueryString or POST buffer if (parameters == null) { // look for parameters in the route if (routeData != null) { string parmString = routeData.Values[parameter.Name] as string; adjustedParms[parmCounter] = ReflectionUtils.StringToTypedValue(parmString, parameter.ParameterType); } // GET parameter are parsed as plain string values - no JSON encoding else if (HttpContext.Current.Request.HttpMethod == "GET") { // Look up the parameter by name string parmString = Request.QueryString[parameter.Name]; adjustedParms[parmCounter] = ReflectionUtils.StringToTypedValue(parmString, parameter.ParameterType); } // POST parameters are treated as methodParameters that are JSON encoded else if (paramType == CallbackMethodParameterType.Json) //string newVariable = methodParameters.GetValue(parmCounter) as string; adjustedParms[parmCounter] = serializer.Deserialize(Request.Params["parm" + (parmCounter + 1).ToString()], parameter.ParameterType); else adjustedParms[parmCounter] = SerializationUtils.DeSerializeObject( Request.Params["parm" + (parmCounter + 1).ToString()], parameter.ParameterType); } else if (paramType == CallbackMethodParameterType.Json) adjustedParms[parmCounter] = serializer.Deserialize(parameters[parmCounter], parameter.ParameterType); else adjustedParms[parmCounter] = SerializationUtils.DeSerializeObject(parameters[parmCounter], parameter.ParameterType); parmCounter++; } Result = MI.Invoke(target, adjustedParms); return Result; } The code basically uses Reflection to loop through all the parameters available on the method and tries to assign the parameters from RouteData, QueryString or POST variables. The parameters are converted into their appropriate types and then used to eventually make a Reflection based method call. What’s sweet is that the RouteData retrieval is just another option for dealing with the inbound data in this scenario and it adds exactly two lines of code plus the code to retrieve the MethodName I showed previously – a seriously low impact addition that adds a lot of extra value to this endpoint callback processing implementation. Debugging your Routes If you create a lot of routes it’s easy to run into Route conflicts where multiple routes have the same path and overlap with each other. This can be difficult to debug especially if you are using automatically generated routes like the routes created by CallbackHandlerRouteHandler.RegisterRoutes. Luckily there’s a tool that can help you out with this nicely. Phill Haack created a RouteDebugging tool you can download and add to your project. The easiest way to do this is to grab and add this to your project is to use NuGet (Add Library Package from your Project’s Reference Nodes):   which adds a RouteDebug assembly to your project. Once installed you can easily debug your routes with this simple line of code which needs to be installed at application startup:protected void Application_Start(object sender, EventArgs e) { CallbackHandlerRouteHandler.RegisterRoutes<StockService>(RouteTable.Routes); // Debug your routes RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes); } Any routed URL then displays something like this: The screen shows you your current route data and all the routes that are mapped along with a flag that displays which route was actually matched. This is useful – if you have any overlap of routes you will be able to see which routes are triggered – the first one in the sequence wins. This tool has saved my ass on a few occasions – and with NuGet now it’s easy to add it to your project in a few seconds and then remove it when you’re done. Routing Around Custom routing seems slightly complicated on first blush due to its disconnected components of RouteHandler, route registration and mapping of custom handlers. But once you understand the relationship between a RouteHandler, the RouteData and how to pass it to a handler, utilizing of Routing becomes a lot easier as you can easily pass context from the registration to the RouteHandler and through to the HttpHandler. The most important thing to understand when building custom routing solutions is to figure out how to map URLs in such a way that the handler can figure out all the pieces it needs to process the request. This can be via URL routing parameters and as I did in my example by passing additional context information as part of the RouteHandler instance that provides the proper execution context. In my case this ‘context’ was the method name, but it could be an actual static value like an enum identifying an operation or category in an application. Basically user supplied data comes in through the url and static application internal data can be passed via RouteHandler property values. Routing can make your application URLs easier to read by non-techie types regardless of whether you’re building Service type or REST applications, or full on Web interfaces. Routing in ASP.NET 4.0 makes it possible to create just about any extensionless URLs you can dream up and custom RouteHanmdler References Sample ProjectIncludes the sample CallbackHandler service discussed here along with compiled versionsof the Westwind.Web and Westwind.Utilities assemblies.  (requires .NET 4.0/VS 2010) West Wind Web Toolkit includes full implementation of CallbackHandler and the Routing Handler West Wind Web Toolkit Source CodeContains the full source code to the Westwind.Web and Westwind.Utilities assemblies usedin these samples. Includes the source described in the post.(Latest build in the Subversion Repository) CallbackHandler Source(Relevant code to this article tree in Westwind.Web assembly) JSONView FireFoxPluginA simple FireFox Plugin to easily view JSON data natively in FireFox.For IE you can use a registry hack to display JSON as raw text.© Rick Strahl, West Wind Technologies, 2005-2011Posted in ASP.NET  AJAX  HTTP  

    Read the article

< Previous Page | 1 2 3