|
LATEST POSTS
Wednesday, November 28, 2007
So I made it to Part 3. Who knew I had it in me? For the uninitiated, I'm braindumping on my meanderings through the Timok sample application. I'd advise you to check out part 1 and part 2, partially because Part 2 includes a disclaimer that says, now that I look at it closely, don't listen to me. So far, we've followed a request through a controller and how to apply filters to controllers. This time, we're finally going to look at some rendered code. When we left off, we had determined that unauthenticated requests to the main page, /home/index.rails, we're redirected to the Index action on the Login controller. LoginController derives from ControllerBase, rather than SecureController. So it will not run the request through the AuthenticationFilter. Instead, the Index action executes normally. That is, it will use the default layout and the index.vm view. So are we finally rendering something on the screen yet? Why, yes, we are. As mentioned in part 1, the default layout will be rendered with the index.vm view in Views/Login. The HTML you see in index.vm is what is rendered on the page. Sort of. We'll take a look at it now. OK, it kinda looks like HTML but I'm having some acid ASP flashbacks Yeah, and it's not as pleasant as you would have hoped, right? The HTML you are looking at is littered with escape sequences that mean something to the view parser. Like classic ASP, these are processed server-side and the view engine will render appropriate HTML based on the command and its arguments. Note that we are using NVelocity as the view engine. It is the default one provided by Monorail but is not the only one. Brail is pretty popular as is ASP.NET web forms, which has a syntax similar to what you are used to in ASP.NET. I have zero experience with either of them so in the immortal words of Handy: Read a book. In the meantime, just assume that anything with a funky character in front, like # or $, is for NVelocity to figure out. We'll look at a couple of these next. #capturefor(head) The text 'twixt this and the #end block will be rendered in the page's <head> tag. $siteroot Generates a base URL corresponding to the base application. For example, if your application resides at http://localhost/Timok.Rbr.Portal, this URL will be substituted in place of $siteroot when the page is rendered. It is like using ~ in ASP.NET web forms. "$UrlHelper.For("%{action='ForgotYourPassword'}")?username=" + $F('username'); This is a busy little bit of code. First is the UrlHelper which is an NVelocity construct that will create a URL for you based on the parameters passed in.In this case, it will build a URL corresponding to the ForgotYourPassword action. $F isn't actually server-side code. It is rendered as-is in the client. $F is defined in one of MonoRail's js files (AjaxScripts.js). It is a sort of shorthand that says, "append the value of the 'username' form field to this URL when this code is executed. And since we don't know what this will be when the HTML is generated, it has to be a client-side function. It is similar to: document.getElementById('username').value $Form elements These are for various form-related functions. $Form.FormTag generates the <form> tag in HTML while $Form.EndFormTag generates the </form> (along with some validation code). $Form.LabelFor and $Form.TextField generate <label> and <input type='text'> elements respectively. I'll leave it to you to figure out what $Form.PasswordField does. #if($error) This should be somewhat self-explanatory. The HTML in this block is rendered only if the "error" server variable is defined. Summary We finally got to look at some HTML even if it looked a little funny. I sorta skimmed over the funky NVelocity syntax for a few reasons: - It's NVelocity-specific. Brail, ASP.NET WebForms, and other view engines will have their own syntax
- The idea should be familiar to you if you've done classic ASP development, even if the syntax is different
- You can view the source of the resulting page just as easily as I can to see what each of these things does
From here, we'll follow through with the form submittal to see what happens when the user actually does log in. Kyle the Moot
Tuesday, October 30, 2007
Oy vay, the hillbilly has to be more careful adding Part 1 to the beginning of a post. Too many implications about his commitment involved. This is a follow up to a post I did to help guide new MonoRailers through the Timok sample application. If you're just joining us, or have hit me from a random search engine (oh, let's just say it: Google), the intent is to help get up to speed with MonoRail by explaining the steps one might go through when looking through a sample application. I haven't been diving too deeply into the topics because I'm not really a deep-diver by nature, unless it is required. Scared I might get the coding equivalent of the bends. A friendly reminder/disclosure/EULA that, for the most part, I'll avoid any "I think"s and "It looks like"s and "My guess is"es for the sake of readability. Consider this your unqualified qualification that anything I say here is the result of my own investigations with a liberal helping of my previous web experience. When we left off, we had gone through how MonoRail routes requests to an appropriate controller and how that controller determines which HTML to render on the page. We walked through a request to /home/index.rails which led us to the default.vm layout in the Views/layouts folder and the index.vm view in the Views/Home folder in Timok.Rbr.Portal.Web. index.vm contains the HTML that will be rendered within the default.vm layout (akin to a "master page"). But before we div---er, wade into index.vm, we need to back up a bit. I tried to navigate to /home/index.rails but was redirected to a login page. WHAT GIVES?!? Open up HomeController.cs again and notice that it derives from SecureController, which in turn derives from ControllerBase, which in turn derives from SmartDispatcherController. SmartDispatcherController is the main MonoRail controller class and all your controllers must derive from it (or its own base class, Castle.MonoRail.Framework.Controller, but that isn't as common). It's common for MonoRail applications to create their own ControllerBase derivation, similar to creating your own PageBase in traditional web forms. In this case, we also further derive a SecureController class which, as its name implies, allows you to secure access to any controllers that derive from it. How does SecureController restrict access to controllers? The class has the following attributes: [Filter(ExecuteEnum.BeforeAction, typeof(AuthenticationFilter), ExecutionOrder=1)]
This tells MonoRail that before any action can be performed on this controller, we need to first process a filter of type AuthenticationFilter. ExecutionOrder is helpful when more than one filter is applied to a controller, which isn't the case here.
Note that the controllers.config file contains an entry for our AuthenticationFilter class. While the above attribute indicates that we have to use a class of type AuthenticationFilter for the filter, it doesn't say which class specifically needs to process the request. This is another example of how MonoRail uses Windsor, the IoC container. By registering AuthenticationFilter in the controllers.config file, we tell MonoRail "if you need a class of type AuthenticationFilter somewhere and one hasn't been specifically requested, use this one".
OK, fine, so how does *AuthenticationFilter* restrict access to controllers then?
I'm not sure I like your tone, kiddo. Maybe I should just leave you to figure this out on your own, yesno?
No, no, no. I didn't mean it like that. I apologize. Please continue.
That's better. AuthenticationFilter (which derives from MonoRail's Filter class) overrides OnBeforeAction. This code will be executed before any action is performed on a controller that uses this filter. And there isn't anything particularly MonoRail-ish in this code. It checks to see if users are logged in using plain old System.Web.Security.FormsAuthentication. If they aren't, they are redirected to the login page. Or rather, they are redirected to the Index action of the Login controller.
If they are authenticated, OnBeforeAction returns true, which means the request will filter through to the originally requested action (in our case, the Index action on the Home controller). The last line of OnBeforeAction says "return false". The code never makes it this far because it either returns true or redirects to the login page before it gets here. But if it did get to this line and returned false, this tells the controller using this filter that it didn't "pass the test". The controller will then display a blank page which you can verify by commenting out both SendToLoginPage lines.
Summary
Two posts and we still haven't actually rendered anything yet. Yeah, well, security has a tendency of grinding everything to a halt. Here we discussed:
- Applying filters to controllers to execute code before an action is processed
- Deriving your own controller hierarchy
- Using Windsor again to provide a class when one isn't specifically requested
- Being polite to the hillbilly
Next up: We'll finally look at some rendered code and, with luck, what happens when you do something on the page.
Kyle the Insecure
Thursday, October 25, 2007
And here we have, three common ASP.NET AJAX mistakes.
I haven't been out Ajaxin' that much lately but reading through that list surfaced some painful, painful memories. And I've dealt with Rogers Wireless Customer Service so I know a thing or two about pain.
The underlying thought that went through my head for each and every one of these mistakes is: Why is the technology so complicated as to allow these mistakes in the first place?
Look at the recommended practices to avoid the mistakes: Litter your code with checks for IsPostBack or IsInAsyncPostBack. Make sure you call events in the right order. And for heaven's sake, put that code in PreRender, not Load. Dummy. And my favorite from the intro: "this...means that using the UpdatePanel requires careful attention to the ASP.NET Page Life Cycle."
Now I don't want to be a hippo-critter-cal hillbilly. I did, at one point, live and breathe the page life cycle and saw no never mind to it at the time. But it's interesting how the introduction of alternatives can change one's perspective. Nowadays, I look back at when I dealt with OnInit, OnLoad, OnPreRender, OnRender and wonder if I sounded like some crazed Santa Claus when I talked to other people about it.
Kyle the Commonly Mistaken
Saturday, October 20, 2007
In my latest effort to pad out my posting count, I'm going to take a sample MonoRail application and annotate it. The reason being: I would have liked one myself. Yes, I can download samples and try to grok it by flipping back and forth 'twixt code and the API Reference Manual. But when I'm looking at a sample app, there are a lot of times I ask "why are you doing it this way?". And there are times where I just plain don't feel like slogging through documentation looking for the section that applies to a specific piece of code. That's about all I'm going to do by way of explanation because this will probably be a long enough post as it is. The sample app I'm going with is the Timok Portal Project prepared by the Castle folks themselves. I considered also the source code for the ALT.NET conference website (or at least a version of it) but frankly, I'm a little scared to say ALT.NET these days for fear that the Pedantic Police will take me away. This little adventure will assume little knowledge of MonoRail other than what it does conceptually. It also assumes you are familiar with traditional web forms and trying to map this new world into what you know. It's laid out as if you are first opening the app and trying to navigate your way through the flow starting from default.aspx. So I will jump around from topic to topic but it's meant to answer questions as they would theoretically occur chronologically. Whenever there are no references to explicit explanations, it is essentially my understanding of how things work. So take it as such. So without further adieu, we'll see how far we get today... Default.aspx Your standard MonoRail default page. It does nothing other than redirect you to the "real" main page: /home/index.rails. It exists because very likely, the IIS directory is configured so that default.aspx is the default page. OK, so let's take a look at index.rails. Waitaminute... It doesn't exist. And in fact, you may also be looking for a home directory off the root. Stop thinking of things in terms of files and directories. If you look in the web.config, there is a section called <httpHandlers>. The first one in the list says that any time ASP.NET finds a URL request that ends in .rails (excluding the query string), process that request with the MonoRailHttpHandlerFactory. That factory parses the URL and decides what to do with the request based on what it finds. And 99% of the time, that *doesn't* involve navigating to and processing an aspx file. To continue from default.aspx, the page redirects you to /home/index.rails. In MonoRail-speak, this means: Find the controller for "home" and process it using "index" as the action to perform. How does it know where the home controller is? Back to web.config. The <castle> section lists references to a bunch of other config files. One of these is controllers.config, which lists all the controllers used in the application. The one we are interested in is home.controller, which refers you to the HomeController class in the web project. How does it know to look at the "home.controller" element? Through the magic of convention and the Windsor IoC container. If you're not familiar with Windsor or IoC, think of it as a way of helping the application to find things it needs when they aren't explicitly provided to it. In this case, Windsor is helping the application to find which class to use when we request the home controller. In this case, it's HomeController.cs in the Controllers folder of the web app, as can be seen from the home.controller component. So where's the HTML that HomeController renders? It may not seem obvious but there are other files associated with this class, similar to how an aspx file is associated with its code-behind/code-beside file. The controller has two attributes attached to it: Layout("default") and Rescue("generalerror"). The Layout attribute tells us which layout to use when rendering the page. Layouts are stored in the layouts folder in the web project. This is always where MonoRail looks for layouts which is why there is no explicit link to the folder from the controller. Layouts are analogous to master pages and I'll leave it at that for now. If you open the layouts folder, there is only one layout: default.vm. Coincidentally, the same name as was used in the Layout attribute of the home controller. (Note: It's not really a coincidence.) So at this point, we have the controller telling us which layout to use to render the page template. Default.vm contains mostly HTML with some "other stuff" thrown in. The only "other stuff" I'm interested in at the moment is $childContent, which is analogous to the PlaceHolder ASP.NET server control in a master page. This is where the individual content goes for each controller that uses this layout. The HTML that goes into that placeholder is located under the Views folder in the web project. Specifically, it is in Views/Home/index.vm. Again, there is no direct link telling the controller to go to this file specifically. Rather, Monorail will look under the Views folder for a subfolder matching the name of the controller. And also note that the name of the file, index.vm, matches the name in the URL we are requesting: index.rails. Minus the extensions. Again, not a coincidence. One final note on the controller. It contains a method called Index which, by this time, should give you some indication that it is important with our request for index.rails. This method will be executed before the index.vm view is rendered. And again, nowhere does it explicitly say, "if you are requesting index.rails, execute the Index method in HomeController". The underlying link in all of this is just the name of the request: index. Summary In our request for /home/index.rails, the following actions were taken: - The request was routed to MonoRailHttpHandlerFactory because it ended in .rails
- The factory parsed the URL to determine which controller should be used to render the request. Using the Windsor container, it determined that we should use HomeController to render the request
- HomeController executed the Index() method, loaded the default.vm layout, and inserted the index.vm view into it and rendered the result.
One of the underlying themes you may have seen is the reliance on "convention over configuration". MonoRail knows where to find things because of the conventions used. Views are stored in the views folder, layouts in the layouts folder. The Index method is executed because we are responding to the index.rails request. Compare this with an aspx page where there is an explicit link 'twixt it and it's underlying code-behind file (via the Inherits attribute on the <@Page@> directive). This is (hopefully) the first in a series because, quite frankly, we haven't covered much yet. Next time, we'll continue where we left off, which is with the index.vm view. But before that, we'll need to talk about why, when you launch the application, you are actually first re-directed to the login page. Kyle the Derailed
Saturday, October 13, 2007
Strolling through some Visual Studio tips courtesy of Chinh Do. Some good tips although some go away with ReSharper (and we won't get into the part in Tip 4 where he says "Regions [are] a great way to organize your code". For now, I'll focus on Tip 6: "Attach to Process" to Start Debugging in ASP.NET. A quick summary: If you already have the application running in a browser, you can "attach to process" rather than pressing F5 to compile and run the app. The idea being that you don't need to launch your application and navigate to where you need to be. Here's my own preferred method which goes along the same lines. Like Chinh, I launch the application in its own browser. (Side note: Usually this means creating a separate virtual directory for it in IIS but if you want to use the built-in web server (Cassini it's called, yesno?), you will have to launch the app from Visual Studio at least once to start the web server.)The next step is creating an empty html page and setting it as the startup page. That's pretty much it. With this setup, you can play around with your code, re-compile (Ctrl+Shift+B), then refresh the browser to see the changes. Like Chinh's tip, there is no need to press F5 to launch the app, then navigate to the page to see your changes. And you can still debug in this method. That's what the blank startup page is for. Launching the app will attach the debug process to your existing browser instance (as well as the instance that is launched when you press F5). So if I do need to step through code on a page, I can set a breakpoint, press F5 to attach the debug process, flip over to my existing browser and refresh the page to hit the breakpoint. The blank startup page serves essentially as a launching pad. The advantages are pretty much the same as in Chinh's original tip. With my method, it's easier to attach to the debugger because all I need to do is press F5, rather than Alt+D, P, "as", Enter (which, truth be told, is still pretty quick). With his method, you manually stop debugging (Shift+F5). With mine, you can still do that or you can close the startup page to do the same thing (at least in IE, Firefox doesn't do the same thing). Having said that, Chinh's method has one serious advantage over mine (and over debugging with Visual Studio using F5 in general): It doesn't matter which browser you use. If you want to use Firefox, you don't need to muck with Visual Studio to set it as your default browser. You can launch your application in both browsers, attach the aspnet_wp process, and refresh either one (or both) and your breakpoints will be hit. So with that advantage in mind, along with some other minor quirks in my method, I'll be switching over to his "Attach to Process" for the time being to see if it makes things easier. Kyle the Detached
Monday, October 01, 2007
One of my contracts involves what is essentially a document management system where users can search for legal documents based on metadata attributes as well as their contents. I've been working on it since before the days of SharePoint and even before Content Management Server was somewhat affordable. I mention this to cut off any comments that might say, "Why don't you just use a document management system?" It's in .NET and could benefit from migration to another platform. I'm not going to do it for reasons not worth mentioning. ACCEPT IT! There are two things worth posting about. Neither are new techniques by any stretch. The first is how to search the content and tie that into the metadata search. The second is how to restrict access to the documents (all in Word format) which are not restricted by IIS by default. Searching In order to search the contents of the repository, I'm using a technique that's been around for many moons. It starts with Microsoft Indexing Services (right-click My Computer, select Manage..., and it's under Services). I created a catalog and added the directory containing my documents. Easy enough. Now I have a catalog you can query from code using the Indexing Service query provider. I'd give you sample code but I don't have any; I don't query the catalog from code. It's no good to me on its own. I need to merge the results in with the metadata search in SQL Server. And rather than get one set of results from SQL Server and another from Indexing Services and merging them, I'm letting SQL Server do everything. To do this, I added a linked server to SQL Server: EXEC sp_addlinkedserver MyDocs, 'Index Server', 'MSIDXS', '<Indexing Service Catalog Name>' The first parameter can be whatever name you want. The next two are fixed and the last is the name of the Indexing Service catalog. From here, you can query the results directly from SQL Server and join them with any other query you want. For example: SELECT MetadataField1, MetadataField2, DocumentFileName FROM doc_metadata dl INNER JOIN OpenQuery( MyDocs, 'SELECT Filename FROM SCOPE( ) WHERE CONTAINS( Contents, ''<search term>'' ) ') q ON dl.DocumentFileName = q.Filename WHERE <filter conditions> And just like that, that squirrel's done, as my pappy used to say. The Indexing Service includes a bunch of properties you can return if you like, but for my poor man's document management system, all I need it for is to filter the list of search results. NOTE: Out of the box, the Indexing Service will index all forms of Office documents. For anything else, you'll need to find an appropriate filter that plugs into the service. Adobe makes one for PDFs but that's the extent of my knowledge. Restricting access to Word documents The application uses Forms Authentication to ensure you have appropriate access to the system. There are three roles: admin, subscriber, and guest (and an implied fourth role: ya can't git in). With the default forms authentication setup, anytime you navigate to an .aspx page, it will automatically redirect to the login page. This doesn't hold true for "unmapped" file extensions, such as image files or documents. By "mapped", I mean that IIS recognizes the extension and maps it to an ISAPI filter. Whenever IIS receives a request for a file with an extension it knows about, it filters the request through the corresponding ISAPI filter, which can then perform whatever funkiness it needs to before and/or after the request. Without getting too technical about the ASP.NET ISAPI filter (mostly 'cause I don't know too much about its inner workings including whether it actually *is* an ISAPI filter vs. an ISAPI application), I wanted any requests to Word documents to redirect to the login page if the user hadn't logged in. The same as any other page. So in IIS, I went to the application properties and added a mapping for .doc files (from the Virtual Directory tab, click Configuration..., then Mappings) to the ASP.NET executable (usually C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll or something akin). With that in place, users can no longer navigate directly to Word documents. Such requests will be re-directed to the login page. But there is one last requirement: guests aren't allowed to view documents. Easy enough: add a separate web.config to the documents folder restricting access only to subscribers and admins: <?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<authorization>
<allow roles="subscriber, admin" />
<deny users="*" />
</authorization>
</system.web>
</configuration>
Note: You can also accomplish this with a <location> element in your application's main web.config file. I picked this method because I have a feeling I'll be moving the documents out to a separate virtual directory altogether very soon.
And that's that. I shan't go into the details of setting up your roles but as you may have guessed from the web.config, that is a requirement in order for this to work. It's pretty straightforward Forms Authentication stuff so Google should be able to help you out easily enough. If not, my door is always open.
So with these two techniques, I now have a method for users to search the contents of documents without allowing them to actually open them. Maybe I can get a job at www.experts-exchange.com.
Kyle the Restrictive
Monday, September 24, 2007
I really do need to be more careful about what I say. But in my defense, there is no way that I could have known that an innocent little post on Silverlight would lead to accusations of bestiality. But even without that nice little image of canine sodomy, I need to choose my words more wisely. And I get the impression from my previous post that I wasn't totally clear on my position. So I'll start by confirming that I am very excited about Silverlight. As I was with Javascript DOM manipulation, XML/XSL, XMLHTTP, and ASP.NET AJAX when each of them came out to make our lives "better". In case the tag cloud doesn't make it obvious, my interests lay in the web space. And Silverlight is almost as webby as you can get. And so, while my recent professional development has led me down some strange and wondrous paths, I will always make room in my calendar for a shiny new web technology like Silverlight. My confusion was with the context around it. I.E. Why would you use it? (and I mean that as an honest question, not a sarcastic one). In what cases would you use Silverlight vs. a traditional web app vs. an ASP.NET AJAX one, for example. And in what cases would you combine two or three of those? Such were the questions swirling through my head when I sat down to speak with John Bristowe, who graciously agreed to guide a friend and me through the tumult. Side note: There is still a good sixty to seventy percent chance I would say this even if I didn't know John was going to read it but I've always appreciated his tendency to speak frankly about the technology he evangelizes, especially when talking to him directly. Not in an in-your-face, "I may work for Microsoft but I'm still a rebel" kind of way. He focuses on what it can and can't do in a very matter-of-fact way. He clearly knows his audience and their tendency to turn jaded when they detect marketing-speak so there's little sugar coating. But at the same time, he still paints things in a positive light. Anyway, that's enough Bristowe-love for now. We discussed the many pros and cons of Silverlight of which I'll highlight only a couple here. None of the major cons struck me as being a big deal. Yes, it's early in the product's lifecycle and the tool support is still under development. But given that my favorite HTML editing tool is Notepad2, I'm okay working directly with XAML. At least I can use an XML editor if only to validate my work in some small way. In any case, I have no doubt the tool support will be there from someone when I eventually need it. The pros were more interesting. The obvious one is the development environment. I.E. Building apps in a managed environment. This is one I kind of slammed in my last post. I shouldn't underestimate the impact of being able to write client code in C# and I welcome the opportunity but I'm also not going to shy away from a little Javascript if the situation warrants it. And for those of you who can't wait until the Silverlight 1.1 release, there are alternatives. Regardless, the fact that I can use base class libraries in a browser is a nice-to-have for me, not a make-or-break selling point. I'm just not feeling enough pain, I guess. Or rather, I'm of the opinion, "Find out what the user wants and build it. Somehow." If it involves technology that you're not familiar with or that is cumbersome, suck it up and learn. That's why you build software and users don't. To me, the more important benefits are: the performance gains for really process-intensive client code (orders of magnitude in the hundreds!), dynamic assembly loading, and isolated storage. These seem to be more user-focused improvements over the current model. Performance gain is an obvious one but isolated storage opens up doors for customized user experiences. And dynamic loading means better perceived performance (which, as I've mentioned before, is more important than actual performance). Plus it means you can introduce more user controls in a seamless way. As my friend said afterward, it's almost as if you can extend HTML which has been notoriously resistant to extensibility for nigh on twenty years. The fact that it integrates with my existing knowledge base (Javascript, ASP.NET AJAX) is also a big plus. It means Silverlight becomes a tool I can use when it makes sense. For example, I don't need to rewrite the entire application in Silverlight if I need some funky animation in one corner of the screen. I can drop in a control (or more likely, outsource it to a designer who knows how to make these things pretty) and carry on pretty much like I normally would. If the application calls for some fairly extensive processing and a lot of calls back and forth to the server, again, I now have another option. Before John's initial presentation, I had a distorted view of what Silverlight would mean in my development world. Like it would revolutionize how I write my web applications. Afterward, I think I felt it was shifted back to normalcy but I felt there was something there I wasn't getting because its capabilities seemed to differ quite drastically from that distorted view. But then, we didn't really focus on the parts of Silverlight that make the marketers drool: namely, the media capabilities. The parts you will start seeing on the public websites for big corporate-type companies. My dissonance came because I think the hype applies more to these types of websites as opposed to the internal business apps I typically work with on a day-to-day basis. I hope through all this philosophical rambling that it's clear that I did get the context I was looking for. The key to all of this, as it always is, is to remain focused on the end user. Given what I know of Silverlight's capabilities, what can I bring to the application that would make the user experience better? That was the underlying theme to the questions I had and I came away from our discussion much clearer on its place in my own personal world. Kyle the Silverlit
Friday, September 21, 2007
I'm faced with a bit of a quandary, which isn't so unusual except that this time, it doesn't involve a sister-cousin and a priest. I have carte blanche to work on an updated version of an application for my dad's company. And excited am I at the prospect of applying some of my recently obtained knowledge in a relatively unrestricted space. The quandary I've been mulling over, though, is the UI. The original app is web-based and seven years old when choices were fairly limited when you built an app that needed to be accessible in multiple offices. It is fairly XML/XSL/XMLHTTP-y which is what I was into at the time but for the most part, it's your average everyday ASP app. Fast forward to 2007 and your options include, but are not limited to: "Traditional" ASP.NET, ASP.NET AJAX, Smart Client/ClickOnce, Ruby on Rails, Silverlight, SharePoint, MonoRail, Spring.NET, ASP.NET AJAX Control toolkit, CAB (okay, I'm not really serious about that one), WPF, WCF/Web Services. And various combinations thereof. And those combinations can be a little tricky. How does ASP.NET AJAX fit in with Silverlight? Can I reasonably use ASP.NET AJAX Controls within a MonoRail view? Is it even possible to get CAB to compile? It seems that making a decision to use one of these may have an impact on how to (or even whether to) use others. So let it not be said that having free reign on a project is always a good thing. At present, I'm planning to fall back on my standard consulting strategy. Namely, start with technology that makes sense for the project and put all the shiny ones on my wish list aside. If I can justify at least investigating using any of them later, then I will. Not that that makes the decision any easier. "SmartClient or web app?" is a pretty fundamental question with pros and cons on both sides. Hopefully, my one brother will insist that he has to be able to use it at home on his iMac in which case, I don't have to think about it. After that, I'll start with MonoRail (and add "of course" to that statement to make it sound like I roll with the big boys) and see where life takes me. I've said it before: It's hard out here for a hillbilly. Kyle the Chosen
Sunday, September 02, 2007
I recently attended John Bristowe's presentation on Silverlight. He was great as always and gave a good overview of the technology but I left the room not being as excited about Silverlight as I was when I went in. Which isn't to say I'm not stoked about it. I'm a big AJAX fan and the idea of doing some of the more complicated or labour-intensive stuff in managed code is appealing. But there has been a tremendous amount of buzz on Silverlight. I've been following Tim Heuer's recent adventures in it with a tinge of jealousy because I'm still not playing with it a lot. And when Ray Ozzie touts the next big thing, people listen. I had done my own "hello world" app early on and was suitably impressed. In the intervening months, the buzz just kept growing and growing to the point where I went into the presentation trying to see what else there was to it. I knew it was being positioned as a Flash-killer (or at least that's what the buzz was) but I had to see what I had missed in my XAML. Turns it out, not much. Yes, it's a Flash-killer (whether John wants to say the words or not) but as far as I can tell, that's it. At the end, I was scratching my head about why everyone was so worked up about it. You're still working with textboxes and input buttons and wiring up the events the same way you would in HTML and Javascript, albeit in a *much* easier way. And probably prettier too once the designers get hold of this. You still have the same security limitations of Javascript. In particular, you still can't call webservices outside your domain. (This was one of the problems I thought Silverlight may have solved. They're working on it but for the moment at least, you still need to call back to your own domain.) The essence of my puzzlement is that I don't understand why so many people think this is going to revolutionize the web. I mean that as a genuine question, not a cynical dig. Is it because of the presentation-aspect? That Silverlight can make apps that much more appealing visually? If so, how is it different than Flash? To be sure, the airline demo *is* impressive (and I sincerely hope someone is making an effort to do a real-world version of it). I dunno, maybe I am underestimating the popularity of Flash. It doesn't seem like a very threatening technology to kill off. I'm probably not recognizing the value of the media-centred features of Silverlight as well. This is probably the big selling point for the executives at Microsoft, especially in an era where YouTube can be sold for $1.65b. More likely, I'm probably underestimating the pain new web developers are feeling trying to get Javascript to do things people have come to expect from their web apps. Early in the presentation, John asked, "Who *likes* working with HTML, CSS, and Javascript?" It was a loaded question and I didn't want to get him off-track early in the presentation but to be honest, I do. Not at the expense of "real" development but I actually don't mind diving into Fiddler with XMLHTTPRequest objects, spewing alerts all over the screen. Not all day, every day but I like mucking with the DOM in a crappy dynamic language once in a while. It's my version of slumming it. Silverlight is still in the top three on my technology wish list. I can think of quite a few applications that could benefit from it, not the least of which is the near-defunct music player I work on in fits of ambition. So I'll fiddle around with it in the coming months because it fits with my sensibilities. And if I'm lucky, it'll be as popular as everyone says it will and I'll be able to keep the young'un fed for the next couple of years. Kyle the Aligned
Thursday, May 10, 2007
One of the things I've always hated about my otherwise-dashing Coding Hillbilly theme is that there was no easy way to get back to the home page. Normally, it's a pretty easy thing to do. Apply an anchor tag to the text and/or image in the title and away you go. Unfortunately, I made a design decision early on that prohibits this. The image you see at the top is actually a background image for a <div>, not an <img> tag. Originally it was an <img>. But when I did that, I noticed the browser would start throwing up horizontal scroll bars when it was resized to be not as wide as the image + the search bar. And while I don't mind forcing users to scroll when the actual text warrants it, I *hate* forcing it just because you're proud of your pretty picture. So I made it a background image and lo! I could now resize the screen so that the search bar can overlay that image if a user so desires. But it meant that there is no actual content to which I could apply an <a> tag to get users back to the home page. What to do, what to do. Enter my CSS archnemesis: spacer.gif. Oh, how I loathe you and the fact that people still use you for layouts even though you are no longer necessary. But you still can be useful. All I need to do is add you to the <div> at the top with an anchor tag and people will click you thinking they are clicking the image! So that lasted about ten minutes until I came to my senses. A freakin' transparent gif filling the entire header? Not on my blog, sister. The eventual solution: modify the <td> that makes up the left part of the header: <td style="cursor:hand;" onclick="location.href='/'"> Yeah, Firefox doesn't recognize "cursor" in CSS but it's still better than nothing. *UPDATE* Guess I'm showing my age. Firefox does support "cursor" in CSS. Just not cursor: hand. The correct, non-IE-specific version is cursor: pointer.
Tuesday, August 01, 2006
I'm no designer but there are a couple of things I know I like. One of them is max-width. On my first attempt at a theme, I fixed the width at 775px. I've never liked doing that because it looks so crappy on my 1600x1200 resolution laptop. By the same token, I'm getting too old to read text that scrolls across that entire screen.
So what I really want is to say, "expand this as the window expands, but only up to a point." In other words, I want to set a maximum width on my content.
That's what the max-width CSS property is supposed to do and that's exactly what it does do in Firefox. IE6 doesn't support it but there is a workaround:
width: expression( document.body.clientWidth > 990 ? "990px" : "auto" );
Seems IE lets you insert javascript into your CSS which was easier for them to implement than just following the CSS spec...I guess...Whatever, the reason, my theme uses that (plus a little additional ditty to impose a minimum width) and now I get what I want.
But not without some problems. When I tested it originally in my theme, the maximum width worked in that it wouldn't go past 990px. But it also wouldn't adjust when I made the window smaller than that. In essence, I had a fixed width 990px DIV. But I had seen this working in practice so I couldn't figure out why mine didn't work.
It wasn't until I removed the DOCTYPE declaration for loose.dtd at the top of my theme that it actually did start working. Weird.
The only other major thing I wanted to change is the image at the top. I switched it from an explicit <img> to a background-image so that, again, I could make my page more liquid without having scrollbars appear at inopportune moments.
And it's *$%-ing annoying having to support two browsers again. One of them had better win this war soon...
Disclaimer
The opinions expressed herein are my own personal opinions and do not represent
my employer's view in any way.
Copyright © 2008 Kyle Baley. All rights reserved.
|
|
|
LATEST POSTS
POPULAR POSTS
LINKS
BLOG ROLL
|
|
CATEGORIES
ARCHIVE
| December, 2007 (8) |
| November, 2007 (8) |
| October, 2007 (23) |
| September, 2007 (15) |
| August, 2007 (8) |
| July, 2007 (6) |
| June, 2007 (11) |
| May, 2007 (19) |
| April, 2007 (14) |
| March, 2007 (3) |
| February, 2007 (4) |
| January, 2007 (7) |
| December, 2006 (5) |
| November, 2006 (9) |
| October, 2006 (11) |
| September, 2006 (14) |
| August, 2006 (11) |
| July, 2006 (15) |
| June, 2006 (8) |
| May, 2006 (10) |
| April, 2006 (12) |
| March, 2006 (3) |
| February, 2006 (7) |
|
|
|