Mike is currently… getting whipped at Halo |
|||||||||||||||||||||||||||||||||||||||||||||||||||
[ subversion book ] obligatory book plug [ syndicate ] rss 2.0 feed for boy meets world [ contact ] drop me a line [ about ] this is mike mason's weblog [ eskimoman.net ] original web pages |
Mon, 30 Apr 2007Disabling Export Formats in Reporting ServicesReporting Services 2005 doesn’t allow you to selectively disable export formats for your reports. You can disable export formats for the whole server, but this is a bit useless in a shared environment. For my current client, we wanted to disable XML, Tiff and “web archive” export on all of our reports, but not affect any other reporting applications deployed on the server. Our reports consist of custom parameter pages followed by a report view page onto which we’ve dropped a ReportViewer control. When the page loads, we programatically set the ReportViewer’s server URL, report path, and parameters. We’re doing this to ensure users are requesting reports for data that they’re allowed to see and not tricking us into revealing other users’ data. Whilst there’s no official way to disable export formats on an individual report, a little bit of exploration using Reflector reveals that the ReportViewer contains a ServerReport that acts as a proxy between the control and the Reporting Services web service. The ServerReport allows you to list rendering extensions—these guys do the hard work of actually exporting in each format—but it doesn’t allow you to set the visibility of an extension. Reflection to the rescue! The following code sample turns off XML, Tiff, and “web archive” export for a particular ReportViewer or ServerReport: using System.Reflection; using Microsoft.Reporting.WebForms; using Microsoft.SqlServer.ReportingServices2005.Execution; namespace MyProject { public class ServerReportDecorator { private readonly ServerReport serverReport; public ServerReportDecorator(ReportViewer reportViewer) { this.serverReport = reportViewer.ServerReport; } public ServerReportDecorator(ServerReport serverReport) { this.serverReport = serverReport; } public void DisableUnwantedExportFormats() { foreach(RenderingExtension extension in serverReport.ListRenderingExtensions()) { if(extension.Name == "XML" || extension.Name == "IMAGE" || extension.Name == "MHTML") ReflectivelySetVisibilityFalse(extension); } } private void ReflectivelySetVisibilityFalse(RenderingExtension extension) { FieldInfo info = extension.GetType().GetField("m_serverExtension", BindingFlags.NonPublic | BindingFlags.Instance); if (info != null) { Extension rsExtension = info.GetValue(extension) as Extension; if(rsExtension != null) { rsExtension.Visible = false; } } } } } I really hope Microsoft includes this functionality in the next release of Reporting Services. It would be really quite simple to include it in the graphical report designer and avoid this nasty reflection hack entirely. At the very least, the sealed RenderingExtension class could have a mutable “Visible” property, rather than the read-only property it has now. Posted 23:11, 30 Apr 2007. [ permalink ] Wed, 21 Mar 2007Card InfectedThis whole Agile thing has messed me right up. It’s not the most original idea—Joe Walnes had a card wall for renovating his house, where estimates were in money-costs rather than time—but it works well for me. I find myself getting a little stressed out when a personal project, even just “stuff I should do this week,” doesn’t have a card wall. Now that our wedding project has been successfully deployed I’ll be starting a card wall for happily ever after… Posted 19:07, 21 Mar 2007. [ permalink ] Sat, 17 Mar 2007CVS to Subversion Experience ReportMy current client in Calgary recently switched from CVS to Subversion. Our main goal for switching was to fix performance problems with CVS, but we also hoped to get some benefit from the improved features within Subversion. The CVS repositories were on a reasonably beefy Sun box but we’d been seeing “waiting for lock” messages and frequent hanging of our CVS clients. The server didn’t look like it was under load and switching the repositories to their own mount point didn’t fix the problem. One of the teams also wanted to clean up their branching structure–after five years of CVS they were in a bit of a mess. Our first conversion was straightforward. We wanted to convert a recent project from its existing home in a CVS module into Subversion. We used cvs2svn to do the conversion and ended up with around 6,000 revisions in Subversion. This represented about 18 months of effort from about a dozen developers, and the conversion took about 2 hours to run. The team’s developers had been briefed on the conversion and all checked in to CVS beforehand, then checked out from Subversion once we were ready. The entire team–including business users, analysts and testers–upgraded from TortoiseCVS to TortoiseSVN and pretty much carried straight on with their work. We got the performance improvement we had hoped for, with a Subversion update taking around ten seconds compared to CVS’ one or two minutes. This is with the repository on the same Sun server, the only thing we needed to do was actually install the Subversion software. The second conversion was more complicated. We wanted to take a 5GB CVS repository with five years of history and not only upgrade to Subversion, but sort out some branching problems. One of the branches within CVS had started out as a release branch but evolved into its own product maintained by a separate team. We also had a fairly complicated set of branches we didn’t want to include, tags that were no longer worthwhile, etc. We scripted the conversion by customizing the example cvs2svn-example.options file included with cvs2svn to get exactly what we wanted. The big “Eureka!” moment came when we realized that promoting the CVS branch to its own product was really easy once everything was in Subversion. cvs2svn converts branches and puts them into their own directory, but there’s nothing stopping us from moving a directory within Subversion. We simply copied the branch-that-is-a-product into a higher level, mirroring a regular project’s structure, then deleted its old location so developers wouldn’t get confused about which was the right one. Converting the 5GB, five year old repository took around 16 hours over a weekend. Shuffling directories around once converted took only a few minutes, and we used the excellent TortoiseSVN Repository Browser so all our move operations ran directly against the repository and were lightning fast. Posted 15:42, 17 Mar 2007. [ permalink ] Wed, 14 Jun 2006Pragmatic Version Control Using Subversion, Take TwoI’m very pleased to announce that the second edition of Pragmatic Version Control Using Subversion has been published and is now shipping. As an author, it’s great to get an opportunity to update a published book, and for there to be enough interest that making an update is worthwhile. Since the book first came out Subversion has come a long way, from version 1.0 to 1.3, adding new features and making improvements. I’ve also had a bunch of feedback on what people did and didn’t like in the book and this was a good opportunity to add some more content and address some of that feedback. The book is still very much a guide for using version control in a pragmatic fashion, suitable for people who are new to version control as well as those with prior experience, but the new edition adds some more advanced stuff like programmatic access to a repository, path-based security, and file locking. It’s my continued pleasure to work with Andy and Dave—if you’re an aspiring author with an idea for a book you should seriously drop them a line. The Pragmatic Programmers’ editorial expertise and publishing system is second-to-none, and best of all you won’t have to write your book using Word! Posted 18:29, 14 Jun 2006. [ permalink ] Wed, 15 Feb 2006Model, View, Presenter with ASP.NET 2.0Most people are familiar with the Model, View, Controller pattern (MVC) for separating business logic and presentational logic within an application. MVC is implemented in a number of Java web frameworks, such as Struts and Spring. A more recent pattern–Model, View, Presenter–can be applied in contexts where there is no central “controller” for the application. One such framework is ASP.NET. My team recently built an MVP-based application on ASP.NET 2.0 and had great success with highly testable presenters and a highly adaptable presentation layer. In fact, we chose to switch from creating custom web controls to using simple .aspx pages and didn’t have to change our presenters at all–it’s always nice to validate those previously abstrct design decisions! The MVP pattern separates three elements. The model is one or more domain-specific objects representing the current state of the system, the information we’re trying to display, etc. The view is how we present that information to the user and handle input, usually a particular screen or web page. The presenter is the logic that ties together the model and the view, handles navigation, business logic requests, and model updates. For MVP in ASP.NET 2.0, we use an .aspx page–or more precisely, the code behind partial class–as the view, custom domain objects as the model, and a Plain Old C# Object (can I steal the term POCO?) as the presenter. Let’s assume we’re creating a page to list customers in our application. Our ListCustomers.aspx page might look like this: <asp:Content ContentPlaceHolderID="Main" Runat="Server"> <h1>Customer List</h1> <asp:GridView ID="customerGridView" AutoGenerateColumns="false" runat="server" SkinID="CustomerGrid"> <Columns> <asp:BoundField HeaderText="Customer" DataField="Name" /> </Columns> </asp:GridView> </asp:Content> Nothing special here, we’ve just defined a GridView which will list the customers and display a title. What’s interesting is the code-behind: public partial class ListCustomers : System.Web.UI.Page, IListCustomersView { protected void Page_Load(object sender, EventArgs e) { ICustomerService customerService = ServiceRegistry.GetService The code-behind partial class implements IListCustomersView, which we’ll see in a moment. When the page is loaded we create a new ListCustomersPresenter, passing it the view (this) and anything else it requires (in this case, an ICustomerService). We then call the presenter’s PageLoading() method. What’s happening is that the code-behind is making no decisions about what to display on the page, it simply delegates to the presenter for any non-display-related business logic. The IListCustomersView interface defines how the presenter can interact with the ASP page. There’s just one settable property, Customers: public interface IListCustomersView { List<Customer> Customers { set; } } Looking back up at the code-behind, you can see that the implementation of the Customers property sets the grid view’s datasource to the list of customers and then calls DataBind() to populate the grid. Let’s take a look at the final piece of the puzzle, the presenter: public class ListCustomersPresenter { private readonly IListCustomersView view; private readonly ICustomerService customerService; public ListCustomersPresenter(IListCustomersView view, ICustomerService customerService) { this.view = view; this.customerService = customerService; } public void PageLoad() { List<Customer> customers = customerService.GetAllCustomers(); view.Customers = customers; } } When our presenter is constructed the two things it depends on, the view and the customer service, are passed to it (in this case, by the code-behind). This is known as constructor dependency injection. In the PageLoad() method the presenter simply accesses the customer service to load customers and sets this information on the view. This simple example can be extended to include input (the view can have read-only properties that correspond to text boxes, etc) and action (add a button to your web page and in the code-behind for its click call an action method on the presenter, like AddCustomerClicked()). So why is this useful? Why not just have the code-behind access the CustomerService to load the customers? One of the main benefits is that the difficult business logic is captured in the presenter and can be more easily tested. Because we’re using dependency injection we can instantiate the presenter in an NUnit test, mock-out the view and service, and check the presenter does the right thing. The “load customers” example isn’t very hard but you can imagine logic that needed to take a set of user input and perform something more complex, such as placing an order. A second benefit is it’s very easy to see how the presenter can interact with the view–it can only use methods and properties on the IListCustomersView interface, which means it’s much easier for us to see the logical interface between the UI and the business layer. Finally, it’s possible to test drive your presenters and views, which tends to lead to simpler, more modular design for the system. I’ve simplified some of the other stuff you’ll need to do in a real application. Screen flow and input validation are good examples. We solved the flow issue by having presenters able to return a “presenter result” object, indicating whether the ASP.NET framework should redirect to another page, stay on the current page, go to a login screen, etc. With input validation and error conditions, we add properties on the view so that the presenter can instruct the view to show a particular error message. You can still use an ASP.NET validator for client-side validation, but the presenter needs to be able to toggle it visible too. We started our application using MVP, implementing the view using custom controls coded in C#. We did this mostly because we envisaged our application as a series of reusable controls, some of which (for example a Wiki control) should be embeddable in other applications. Ultimately we went a bit too far with this and coded some simple screenflow, which wasn’t really reusable, with the same C# controls. We found that layout and other tweaks became fairly onerous and decided to switch to implementing the view using traditional .aspx pages and code-behind. We found that our presenters required no changes at all to be able to accomodate the new view–excellent validation of the MVP design pattern. Posted 22:01, 15 Feb 2006. [ permalink ] Wed, 19 Oct 2005Splitting, Merging, and Organizing a Subversion RepositoryWhen setting up Subversion within an organization, folks will often ask “How many repositories should I create?”—my advice is to just create one repository until you have a concrete need for more. I take this approach because it’s easy to split an existing repository into two. I also remind people it’s not the end of the world if they create multiple repositories and then they need to merge them, because Subversion has good support for splitting, merging, and reorganizing repositories. I’ve never really gone into any detail on how you actually do this stuff, but since I recently needed to merge two repositories I thought I’d share the technique I used. Splitting a repositoryFirst off make sure you tell everyone you’re going to split the repository. The ideal situation is where everyone can check in, go home for the night, leave you to organize stuff, and then come in the next day and start on something fresh. If people can’t commit all their changes you may need to help them relocate their working copy. Once everyone’s committed their changes, close down network access to your repository to be sure no-one’s committing further changes. This might be overkill depending on your situation, but it’s nice to be safe. Next, back up your repository using svnadmin dump to create a dump file. A dump file is a portable representation of a Subversion repository and something you might be using for backups already. We’re going to load the dump file into a new repository, using svndumpfilter to select just the directories we wish to move to the new repository. A typical transcript might look like this: [mgm@penguin temp]$ svnadmin dump /home/svnroot/log4rss > log4rss.dump * Dumped revision 0. * Dumped revision 1. : : : * Dumped revision 37. * Dumped revision 38. [mgm@penguin temp]$ mkdir tools-repos [mgm@penguin temp]$ svnadmin create tools-repos [mgm@penguin temp]$ cat log4rss.dump | svndumpfilter include log4rss/trunk/tools | svnadmin load tools-repos Including prefixes: '/log4rss/trunk/tools' Revision 0 committed as 0. Revision 1 committed as 1. Revision 2 committed as 2. : : : <<< Started new transaction, based on original revision 38 ------- Committed revision 38 >>> In the above sample, I dumped the Log4rss repository into a file called At this point, I can make the new repository available and tell developers where to find it. It’s probably also wise to delete the Merging two repositoriesMy current project recently moved from Chicago to Calgary. For a while we had two teams running, using separate Subversion repositories. When everything moved to Calgary, we needed to merge the Chicago team’s code into our repository. We didn’t want to just import the files, we wanted to include historical information too. We created a dump file of the Chicago team’s repository and loaded it straight into our repository using Organizing a repositoryOnce we’d loaded the Chicago code into our repository we used TortoiseSVN’s graphical repository browser to move the new stuff into our existing directory tree. Here’s a screenshot of the repo browser—it’s a great tool for this kind of thing and made reorganization very simple. We just used the “rename” command to move everything around in the repository, and once done we all checked out the newly organized directory tree and continued working. Posted 16:08, 19 Oct 2005. [ permalink ] Mon, 02 May 2005
|
[ tim bacon ] musings of an xp coach [ ian bourke ] enhancing core competencies since 1976 [ martin fowler ] a cross between a blog and a wiki [ alan francis ] agile != good [ paul hammant ] part of the problem… [ darren hobbs ] the blog formerly known as pushing the envelope [ mike roberts ] on life and technology [ chris stevenson ] skizz-biz [ joe walnes ] joe's new jelly [ rob baillie ] oracle |
|||||||||||||||||||||||||||||||||||||||||||||||||
Registered plugins: SmartyPants, antispam, bloglinks (v0.2), calendar (v0+6i), pluginfo (v1.0), and userstatus (v0.1) |