SQL Server Compact timed out waiting for a lock

by Oliver 28. January 2013 14:26

Today, I faced the exception mentioned in the post title: SQL Server Compact timed out waiting for a lock. The default lock time is 2000ms for devices and 5000ms for desktops. The default lock timeout can be increased in the connection string using the ssce: default lock timeout property. (Plus some session details). Circumstances The exception was thrown in my local dev environment while working on our Orchard CMS based portal software discoverize, calling any page in the portal. Obviously, something was wrong not with a single page but rather with a piece of infrastructure. Interestingly enough, only a few moments before trying to open the web site I had done some database manipulation using SqlCeCmd deleting some unneeded columns from one of our tables. It seems that after that the site broke. Solutions tried I tried to get hold of the DB like this: stop and start the web site in IIS (using appcmd stop site "discoverize" and appcmd stop site "discoverize") – no change take DB offline by renaming the file – waited a few moments, renamed it back – no change! Here I started wondering where the lock is saved – is it inside the DB? took the whole application pool offline and restarted it – bang! That helped. I now have my site back up and running and can continue develepment. Conclusion If you encounter the SQL CE timeout error during development inside a web application, restarting the app's app pool will probably get you back to work. Happy coding!

SQL Server Compact timed out waiting for a lock

by Oliver 28. January 2013 14:26

Today, I faced the exception mentioned in the post title: SQL Server Compact timed out waiting for a lock. The default lock time is 2000ms for devices and 5000ms for desktops. The default lock timeout can be increased in the connection string using the ssce: default lock timeout property. (Plus some session details). Circumstances The exception was thrown in my local dev environment while working on our Orchard CMS based portal software discoverize, calling any page in the portal. Obviously, something was wrong not with a single page but rather with a piece of infrastructure. Interestingly enough, only a few moments before trying to open the web site I had done some database manipulation using SqlCeCmd deleting some unneeded columns from one of our tables. It seems that after that the site broke. Solutions tried I tried to get hold of the DB like this: stop and start the web site in IIS (using appcmd stop site "discoverize" and appcmd stop site "discoverize") – no change take DB offline by renaming the file – waited a few moments, renamed it back – no change! Here I started wondering where the lock is saved – is it inside the DB? took the whole application pool offline and restarted it – bang! That helped. I now have my site back up and running and can continue develepment. Conclusion If you encounter the SQL CE timeout error during development inside a web application, restarting the app's app pool will probably get you back to work. Happy coding!

Using @Html.CheckBox() with a dynamic value

by Oliver 19. November 2012 21:09

I’ve just spent much more time than I’d want on figuring out why the following code wouldn’t give me a checked checkbox, even when I set the ViewModel.Value to true: public class ViewModel { public string Name { get; set; } public dynamic Value { get; set; } } @Html.CheckBox(Model.Name, (bool?)Model.Value) The problem is with the signature of CheckBox, of course! Instead of calling the one where the second argument is of type bool, it calls the one where the second arg is of type object! // the method I thought I was calling public static MvcHtmlString CheckBox(this HtmlHelper htmlHelper, string name, bool isChecked) { return CheckBox(htmlHelper, name, isChecked, (object)null /* htmlAttributes */); }   // the method I in fact was calling public static MvcHtmlString CheckBox(this HtmlHelper htmlHelper, string name, object htmlAttributes) { return CheckBox(htmlHelper, name, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); }   // the method that's being called by the second method above: isChecked == null! public static MvcHtmlString CheckBox(this HtmlHelper htmlHelper, string name, IDictionary<string, object> htmlAttributes) { return CheckBoxHelper(htmlHelper, null, name, null /* isChecked */, htmlAttributes); } Even though they were not strictly necessary, still, the framework sources helped me out this time to find this subtle bug (in my code, of course!). The solution to the problem looks like this: @Html.CheckBox(Model.Name, (bool)(Model.Value == true)) Happy Coding!

URL Rewriting and Routing in Orchard CMS / ASP.NET MVC

by Oliver 28. August 2012 23:41

Working on Marinas.info, we want to create SEO friendly links to specific searches that will hopefully rank high up in the search engines. They should look something like www.marinas.info/germany for marinas situated in Germany or www.marinas.info/wífi for marinas that provide wifi internet access. We also plan on supporting most European languages, some 30+ or so, even if not from the start. Anyway, the number of URLs we will generate is likely to explode, and we need a solution to consistently generate and handle those thousands of different URLs. This post investigates a few solutions that have popped up. External URL Rewriting solutions – UrlRewritingNet and the IIS Url Rewrite Module The two solutions listed here are called external because they integrate with the ASP.NET MVC request pipeline in way that they will be invisible to the actual web application. Routes would be rewritten in an early step and the application would only get to see the rewritten URL that it would know how to handle. UrlRewritingNet Since 2006, UrlRewritingNet has been around and I assume it’s a widespread solution. We use it in Camping.info, and probably the best part is the easy configuration. Still, I remember that we had a few problems with it that needed fixing, so we would most likely have to use that slightly customized version. I’m not 100% sure if it would work with MVC out of the box since we’ve only used it with ASP.NET WebForms. IIS Url Rewrite Module This is a solution by Microsoft that would certainly get the job done, too. I haven’t really used it yet in any larger project though, so I’d have to dive into it first. If you feel like giving it a go, check out http://learn.iis.net/page.aspx/734/url-rewrite-module/. Internal solutions – Orchard Rewrite Rules and ASP.NET MVC Routing These approaches work inside the application. Orchard Rewrite Rules Orchard Rewrite Rules is an Orchard Module that brings (a subset of) mod_rewrite style URL rewriting to any Orchard installation. We’ve successfully used it e.g. to redirect traffic from http://marinas.info to http://www.marinas.info. The greatest benefit is that it’s just another module that you can simply enable and disable at runtime from within the application without a need to recycle the app pool as would be the case for the two external rewriting solutions since their configuration is coupled to the web.config file. The drawback of this solution is that we’re also new to its syntax and it’s not that clear (yet) how we would efficiently map the thousands of routes with their dynamic values that we are aiming at. ASP.NET MVC Routing It seems that ASP.NET MVC’s built-in routing engine can provide us with what we are looking for. At first glance, looking at the standard examples of route definition, it didn't appear that promising. Remember, we want to support URLs such as www.marinas.info/germany and www.marinas.info/wifi for a lot of search categories. The routes to match those request would either have to be very specific, e.g. one per category, or very general, e.g. one for all categories. The first approach would lead to the thousands of routes I mentioned earlier, the latter would also catch requests for other parts of the application that might have nothing to do with search since it’s so general. It turns out there are more advanced features in ASP.NET MVC Routing that allow to overcome these restrictions. Custom Route Constraint with IRouteConstraint and Custom Route Handler with MvcRouteHandler This answer on Stack Overflow to a question concerning exactly the same problem points to a blog post on writing your own Route Constraint which is a great way to deal with the second problem mentioned above, that a too general route would match too many requests. The custom route constraint could e.g. constrain the application of a certain route to only valid values. Another approach, presented in this post on SEO friendly URLs in MVC, would be to derive from the default MvcRouteHandler and implement some custom logic to handle our custom URLs. Conclusion: ASP.NET MVC Routing has it all I’m glad I set out to examine those different solutions because I totally underestimated the power of ASP.NET MVC Routing if I hadn’t. Another great post on Optimizing ASP.NET MVC3 Routing talks about even more of its aspects and how Stack Overflow handles their large number of routes with high performance using (mostly) built-in functionality. Looks very much like this is the way to go! Happy coding!

Using Non-ASCII / Unicode URLs on Your Web Site

by Oliver 24. August 2012 16:22

We’re still working on Marinas.info and were wondering if we should change any of the behavior that we use in Camping.info. There we allow for all kinds of unicode characters, from those in Eastern European languages such as Polish to the Cyrillic letters of the Russian alphabet – but we encode them properly using HttpServerUtility.UrlPathEncode(). This is the behavior that RFC 3986 on URIs defines in section 2.1. It also means that all links that are rendered on pages on Camping.info are correctly encoded and will work in all browsers, even text based ones. Problems with Internet Explorer The drawback of encoded URLs is that Internet Explorer will not decode them in the address the way all other major browsers do (Firefox, Chrome, Opera, haven’t checked Safari), so all those Internet Explorer users out there will see something like http://pl.camping.info/polska/%C5%9Bl%C4%85skie/camping-pod-d%C4%99bowcem-20149/po%C5%82o%C5%BCenie – which is, to put it mildly, unreadable. Go ahead and copy that URL into any of the other browsers and they will reformat it to http://pl.camping.info/polska/śląskie/camping-pod-dębowcem-20149/położenie but behind the scene will still use the encoded URL. Another problem occurs when you enter a URL that contains non-ASCII characters directly into IE’s address bar. The initial page load will succeed as IE properly encodes the URL. But once you want to POST to the same page IE changes its behavior to something in my eyes inconsistent generating an error. A deeper look behind the IE scenes This is what the error looks like in Fiddler: As you can see, IE replaced the Polish special characters from the first three URL segments and encoded only the last part which is also what’s inside the form’s action attribute: Who would have thought! As you can see in the first screenshot, for the URL www.camping.info/österreich/niederösterreich something similar happens with the difference that IE replaces the ö by the byte with value F6 in hex or 246 in decimal. To make the following screenshots I saved the whole request (as Fiddler intercepted it) to a file and looked at it using the hex editor HxD: According to the table http://www.utf8-chartable.de/, F6 is the Unicode code point for the small letter ö, whose UTF-8 representation is C3 B6 which we can find e.g. in the referrer of the same request: So it turns out IE uses 3(!) different encodings to transmit the same letter ö: its Unicode code point, the URL encoded version proposed by RFC 3986, and the UTF-8 encoded version. Wow! Unfortunately, IIS and our application don’t play well with that. Conclusion - Support Encoded URLs anyway We decided anyway to support those encoded URLs for our new portals including Marinas.info to be able to SEO our pages according to their content even through their URL. Maybe IE 10 will decode those URLs in the address bar and get a grip on handling URL and form action uniformly – for their users’ sake! Happy encoding!

Writing Acceptance Tests for an Orchard / ASP.NET MVC Application – using SpecFlow, Coypu (Selenium) and the MvcIntegrationTestFramework

by Oliver 22. August 2012 13:48

When we started development on Marinas.info, we decided to write acceptance tests for all important features of our application. This decision was even more justified by the fact that a bunch of similar platforms are to follow using the same codebase. We wanted an application with less bugs and easier maintenance. Writing good, automated acceptance tests is not easy and it’s not fast, either. For some time now, we’ve been trying to get the first set of our tests run green, which proved especially tricky on our TeamCity continuous integration server. This post investigates a working solution. The ingredients: SpecFlow, Coypu (Selenium), Browser, Web Server, and MvcIntegrationTestFramework SpecFlow In .NET world, using SpecFlow to write acceptance tests is nothing new and has recently become, yet again, more appealing after its update to version 1.9. One of our scenarios for verifying image upload functionality looks like this: It’s simple to write, easy to read and great living documentation. For Browser based tests you need: Coypu (Selenium) Everyone who has written tests for Selenium for even a mildly ajax-y site knows how painful it can be to create reliably working tests. Coypu alleviates the pain and makes test creation as straight-forward as it should be in the first place. Coypu is: A robust wrapper for browser automation tools on .Net, such as Selenium WebDriver that eases automating ajax-heavy websites and reduces coupling to the HTML, CSS & JS A more intuitive DSL for interacting with the browser in the way a human being would A few examples of Coypu’s clean API can be seen here in one of the step definitions for the above scenario (Browser is an instance of the BrowserSession class from Coypu): A web browser To run browser based tests you, of course, need … a browser! Coypu offers support for quite a bunch of them, including the usual suspects Internet Explorer, Chrome, and Firefox. A web server You need to host your application in some web server or another to process requests. Well, this statement turns out to be only partially true, as you will see with the MvcIntegrationTestFramework. But at least for browser based test you need a web server, and you basically have the choice between IIS and IIS Express (if you don’t want to write your own or use someone else’s implementation). We chose IIS Express as it is manageable through a non-administrator account, but it needs to be installed on all machines that will execute the tests. For non-browser based tests: MvcIntegrationTestFramework Introduced by Steven Sanderson in 2009, this small framework allows to write integration tests for ASP.NET MVC applications and execute them without a browser! It empowers you to make assertions on your controllers’ actions’ results rather than on the rendered html output by injecting some clever hooks into your MVC application under test. An example of how a test would look can be found in the above mentioned post. The “magic” of this framework lies in the use of ApplicationHost.CreateApplicationHost() which creates an application domain for hosting your ASP.NET application. Check out this screenshot of part of the source code: How to put the pieces together After a quite radical evolution of our test code (which you can read up on in my follow-up post The Long Road to Browser Based Acceptance Testing), we finally settled for the following: Before the first test starts, setup an instance of the AUT (application under test). This includes: deploying the AUT as we do for our staging environment, but to a temp folder initialize an AppHost instance à la MvcIntegrationTestFramework, i.e. an ASP.NET enabled application domain that hosts the AUT execute the Orchard setup command via the AppHost instance (instead of running the setup through a browser, which we used to do but was a lot slower) Before each test run (SpecFlow scenario) we then execute various commands to setup the environment for the concrete test, e.g.: clean the database simply by overwriting it with a copy we saved after the initial setup create Marina entries that will be displayed and searchable on the site, again, using the AppHost instance Once we want to execute steps in the browser, we do the following: start an instance of IIS Express pointing to the deployed application (we used the wrapper code from Spinning up IISExpress for integration testing) initiate a Coypu BrowserSession which under the hood creates an instance of the browser you choose after battling with Internet Explorer, Chrome, and Firefox Portable, we now use Firefox 10.0.6 ESR (Extended Support Release) because version 10 is of now the highest version supported by Selenium (2.1.25) and the ESR doesn’t ask to be updated all the time After each test run (SpecFlow scenario) we do this: close the browser shut down the IIS Express instance (we slightly modified the above mentioned wrapper code calling Kill() on the process instance after the call to CloseMainWindow() so that it reliably terminates even on TeamCity) Conclusion Setting up a reliable environment for automatically executing acceptance tests has not been a walk through the park but we finally have a solution that basically “just works”. Hopefully, our experience will help you save a couple of hours and also some headache along the way Happy coding!

Asynchronously posting back a form by hitting the Enter key – in ASP.NET WebForms using jQuery

by Oliver 2. August 2012 15:19

On Camping.Info, we lately had a user report that hitting the enter key while in the login form one would be redirected to the search page instead of being logged in. This happened when the focus was still on the password text box because the “Search” button on the page was the first input element on the page (inside the single <form> element that WebForms allows for) of type submit which would by default handle the enter key press event. To improve the user experience, we set out to find a way to postback the correct UpdatePanel – the one which currently has the focus (or one of its child controls). Using an ASP.NET Panel and the DefaultButton property There is a built-in solution to this problem if you’re willing to slightly change your markup and add a hidden <asp:Button> element to your part of the page you want to asynchronously update. You need to wrap your existing html into an <asp:Panel> element and set its DefaultButton property to the ID of that hidden button. This would look something like this: 1: <div class="form21"> 2: <asp:Panel runat="server" DefaultButton="btnHiddenRegister"> 3: <asp:TextBox ID="txtEmail" runat="server" /> 4: <asp:TextBox ID="txtPassword" runat="server" TextMode="Password" /> 5: <asp:LinkButton ID="btnRegister" runat="server">Register</asp:LinkButton> 6: <asp:Button ID="btnHiddenRegister" runat="server"style="display:none" /> 7: </asp:Panel> 8: </div> Of course, you need to hook up the code-behind Click handler for the btnRegister LinkButton to the hidden Button element as well to make this work. The proposed solution will instead have html like the following: 1: <div class="form21 jq-form"> 2: <asp:TextBox ID="txtEmail" runat="server" /> 3: <asp:TextBox ID="txtPassword" runat="server" TextMode="Password" /> 4: <asp:LinkButton ID="btnRegister" runat="server" CssClass="jq-form-submit">Register</asp:LinkButton> 5: </div> Let’s see how we get this to work. Using jQuery On stackoverflow.com, I quickly found this post about a jQuery replacement for DefaultButton or Link where the this answer points to the original solution from March 2009 proposed by this post on fixing the enter key in ASP.NET with jQuery. I’ve improved on the proposed answer in a few ways, so this is what this post is about. The original solution 1: $(document).ready(function(){ 2: var $btn = $('.form_submit'); 3: var $form = $btn.parents('.form'); 4: 5: $form.keypress(function(e){ 6: if (e.which == 13 && e.target.type != 'textarea') { 7: if ($btn[0].type == 'submit') 8: $btn[0].click(); 9: else 10: eval($btn[0].href); 11: return false; 12: } 13: }); 14: }); Remarks: works only if the content is present at the time the script executes, and works only for a single pair of form and form-submit elements. Our improved solution 1: $('body') 2: .off('keypress.enter') 3: .on('keypress.enter', function (e) { 4: if (e.which == 13 && e.target.type != 'textarea') { 5: var $btn = $(e.target).closest('.jq-form').find('.jq-form-submit'); 6: if ($btn.length > 0) { 7: if ($btn[0].type == 'submit') { 8: $btn[0].click(); 9: } 10: else { 11: eval($btn[0].href); 12: } 13: return false; 14: } 15: } 16: }); Improvements The first thing to improve is the registration of the keypress event handler. Since Camping.Info is quite a dynamic site with lots of asynchronous postbacks to the server (mostly using WebForms’ UpdatePanels) a lot of the javascript code we need on our page won’t execute properly as is because it expects the elements it works with to be present at the time of the script’s execution. That’s also the case with the original solution: both the submit button element with class .form_submit and the pseudo-form element .form (I’ve called it pseudo-form element since it’s just a parent element of any type marked with the class .form) must be present when the script executes, otherwise nothing will happen. That’s why – using jQuery 1.7 syntax – we register the keypress event handler NOT on the pseudo-form element but directly on the body using on(). We also the event namespace it by appending .enter to its name keypress so that we can safely remove it (using off()) in case we call the script a second time during postback to prevent it from being attached twice. Please note, that at this point neither the pseudo-form nor the form submit element must be present on the page for this to work. Once the enter key has been pressed anywhere on the page and we’re inside the event handler, we set out to check for a pseudo-form surrounding the element that received the enter key press event and inside it we look for a submit element. [I’ve also changed the class names for those elements by our internal convention to prefix all those that are jQuery related by jq- to set them apart from the CSS class names our designer works with.] Only if we’ve found both those elements, we proceed with either clicking the element if it’s really a button or executing the javascript code that ASP.NET rendered into our LinkButton’s href tag which asynchronously posts back to the server for some update to our page. A subtle but important detail here is to return false (and thus prevent the event from being processed any further) only in case we actually found the pseudo-form and submit elements, so that in the opposite case the default behavior of the page will be preserved. Conclusion The solution presented here works equally well with static and dynamically loaded page content and for any number of forms on your page. It replaces the solution provided by ASP.NET WebForms’ using a Panel and its DefaultButton property, resulting also in cleaner markup. Happy Coding!

A jQuery based tooltip solution for a large web application

by Oliver 13. March 2012 01:37

Finally, with an update we rolled out last week, (almost) all tooltips on Camping.Info look and behave similar, differing mostly in positioning and size, but not in the general look and feel. We chose the jQuery Tools Tooltip as the base for our own solution and it got us pretty far, but there were some pitfalls and scenarios that we needed to handle ourselves. This post is about what limitations we experienced and how we dealt with them. The original As you can read in the jQuery Tools Tooltip documentation, the tooltip plugin is highly configurable. It can take different elements as the tooltip for any given trigger: the value of title attribute of the trigger element the html element immediately following the trigger the html element immediately following the first parent of the trigger an arbitrary html element on the page. You can also position the tooltip pretty much wherever you want relatively to the trigger: Our adaptations Another way to chose the tooltip We found one more useful way to define the tooltip for a trigger element: if the trigger is e.g. a table cell in an html table and you don’t want to specify a static tooltip for some or all table cells but a different one for each cell or at least a number of cells, it makes sense to define the tooltip element inside the trigger (the table cell). Since this effect was not achievable extending the jQuery Tools Tooltip plugin we started changing their source: Breaking the tooltip out of some parent container We also faced some problem properly showing tooltips that needed to “break out” of some bounding box, inside which they were defined (i.e. their html markup). This problem e.g. occurred inside elements with style position: relative, which we have a few of on Camping.Info. Our first attempt was to clone the tooltip element and show the clone instead of the original. This worked in almost all cases – until we tried to attach some more behavior to elements inside the tooltip. The behavior, e.g. some click event handler that we expected to fire when clicking on some element inside the tooltip, wouldn’t execute, since we were working with the clone! So we decided to simply move the tooltip up in the DOM tree for the time it is being shown, more precisely just beneath the form tag that we have on all our pages. We create a placeholder at the place where we removed the tooltip to reinsert it again once it’s being hidden. The code we added to the show() method looks like this: … and here’s the counterpart in hide(): Now, this works quite well everywhere, independent of the position of the tooltip in the DOM tree. Global tooltip configuration Using inline static configuration One feature we quickly missed was some kind of static tooltip configuration without calling  $(...).tooltip({ settings: ... }) for every single tooltip we wanted to create or hook up, respectively. What we came up with is to use the HTML5 data attributes to define any specific configuration statically inside the trigger element’s html markup. Thus, we need to call the tooltip initialization code only once for the whole page. The configuration now looks like this: We use specific prefixes with the data attributes to make them easier to understand, e.g. data-tt-position for an attribute that is used for tooltips and jq-tt-trigger for a class that is used by some jQuery code for tooltips. To process this kind of static configuration we need some custom code that will, at some point, call the original (well, modified by now) plugin code. Unfortunately, the jQuery Tools Tooltip plugin was not designed to allow runtime configuration of the tooltip to show, but we found a way using the onBeforeShow and onHide event handlers. The basic idea is to change the global Tooltip configuration during the first method so that the tooltip we will be showing will be configured correctly, and to reset the global configuration once the tooltip has been hidden again. To achieve this, we iterate over all configuration properties that the jQuery Tools Tooltip plugin supports and search for the respective data attributes on the currently processes trigger element. One example would be the position property: to replace the default value provided by the plugin we look for an attribute that’s called data-tt-position and use its value to temporarily overwrite the default value during the onBeforeShow event handler. Using global profiles Once we had the static configuration working and started to replace all of those clumsy and overly complicated AjaxControlToolkit HoverMenuExtenders, it quickly turned out that we were copy’n’pasting the same configuration in a thousand places. This was not only ugly and violated the DRY principle, it also lead to some unnecessarily bloated html. As a solution to this maintenance nightmare we came up with profiles that comprise a set of configuration options that would else be repeated over and over again: Now, they lead to some really clean html markup: The only change from using the inline static configuration is to use the profile’s properties – everything else stays the same! Conclusion The jQuery Tools Tooltip plugin is a nice, small and highly configurable tool for easy tooltip creation and usage. In a larger web application there a few shortcomings that we’ve addressed here and which we’ve provided working solutions for. We hope to release those changes soon in its own project on our GitHub account. Happy coding!

Orchard and Lucene: getting started with custom search – problems with booleans

by Oliver 12. September 2011 01:46

Update: I filed a bug in the Orchard issue tracker and it’s already been fixed. Nice work! We’ve just started to build our own customized search module. The goal is to have checkboxes for all searchable boolean properties of a given ContentPart and search by checking or unchecking them. In Orchard, one can add contents to the search index using the following code (this is an example for adding a boolean): 1: public class MyPartHandler : ContentHandler 2: { 3: public MyPartHandler(IRepository<MyPartRecord> repository) 4: { 5: Filters.Add(StorageFilter.For(repository)); 6:  7: OnIndexing<MyPart>( 8: (context, myPart) => context.DocumentIndex 9: .Add("DogsAllowed", myPart.DogsAllowed == true ? "true" : "false").Store()); 10: } 11: } Now, when a user checks the checkbox for “DogsAllowed” we want to ask the search index for all documents (Lucene term for what I would call an entity) with the DogsAllowed property set to true. The way we would do that is something along the following lines: 1: ... 2: var searchBuilder = _indexProvider().CreateSearchBuilder("Search") 3: searchBuilder.WithField("DogsAllowed", true); 4: ... The problem with this is: it gives me zero results! Of course, to get something into the index you have to go and save some document/entity for the OnIndexing handler to run, but I’d done that. Somehow I had the feeling that my search was not doing what it was supposed to… So I wanted to know more about the index Lucene had generated so far. Searching for lucene index visualizer lead me to Luke, the Lucene index toolbox which I downloaded v 0.9.9.1 of because it was built against Lucene 2.9.1 and in Orchard the Lucene.NET version is only 2.9.2. Maybe a newer version would have also worked but I got what I wanted anyways. After providing the path to the index files, Luke showed me some interesting stuff, among other things that the boolean was stored as string “True” (mind the upper case!): This behavior is actually no surprise when we look at the source code for the Add(string name, bool value) method, it just calls the Add(string name, string value) method with the bool converted to a string: 1: public IDocumentIndex Add(string name, bool value) { 2: return Add(name, value.ToString()); 3: } It’s good to know that true.ToString() == “True” btw. So, now when I search inside Luke using the query DogsAllowed:True I do get a result – but using DogsAllowed:true I don’t! (The syntax for searches is field:value.)                So now, why does my search (in Orchard) for all documents that have the DogsAllowed property set to true return no results when there obviously is a document in the index with exactly that? Well, let’s look at the implementation of .WithField(): 1: public ISearchBuilder WithField(string field, bool value) { 2: CreatePendingClause(); 3: _query = new TermQuery(new Term(field, value.ToString().ToLower())); 4: return this; 5: } When I debugged through the search I saw that all of a sudden we were searching for DogsAllowed==true instead of True which to Lucene are two completely different things (at least in this scenario). Actually, turning on logging for the Lucene.Services namespace, we get some debug logging telling us what the search is currently looking for: 1: 2011-09-10 00:44:33,026 [6] Lucene.Services.LuceneIndexProvider - Searching: DogsAllowed:true* Now I’m not surprised anymore that I’m not getting any results! This is obviously a bug in Orchard’s Lucene module, but for now I can easily get around it using simply passing the lower case strings to the Add() method myself like this: 1: OnIndexing<MyPart>( 2: (context, myPart) => context.DocumentIndex 3: .Add("DogsAllowed", myPart.DogsAllowed == true ? "true" : "false").Store()); Happy coding!

Orchard CMS: module settings not visible in Admin area? placement.info is the key!

by Oliver 9. September 2011 22:29

Today I went off to create a custom search module for our new Orchard based web application. I simply copied the module Orchard.Search, renamed all namespaces and such to Teamaton.Search, replaced some strings and prepended a prefix of “Teamaton” to a bunch of them. I wanted the new module to be able to run side-by-side with the original Orchard.Search module to make sure I had an independent implementation and there wouldn’t be any conflicts in case the Orchard.Search module is already installed somewhere. A problem I ran into quite quickly was that I wouldn’t see any of the search index’s fields on the Admin page for the new module (to the right you see the settings in the original Search module which is what I expect to see on the left as well):             Searching the discussions on Orchard’s codeplex site, I found this very helpful post on Module site settings not showing up which promised to be the key to my problem. During the initial string replacement orgy, in SearchSettingsPartDriver I had changed return ContentShape(…).OnGroup(“search”) to return ContentShape(…).OnGroup(“TeamatonSearch”). Now, this wasn’t in sync anymore with the Group Id specified inside the SearchSettingsPartHandler, but it should be (as the mentioned post suggests). So I changed that to match the Group “TeamatonSearch” like so: 1: protected override void GetItemMetadata(GetContentItemMetadataContext context) { 2: if (context.ContentItem.ContentType != "Site") { 3: return; 4: } 5: base.GetItemMetadata(context); 6: context.Metadata.EditorGroupInfo.Add(new GroupInfo(T("TeamatonSearch"))); 7: } Unfortunately, it still did not work. Frustration. Another post on the discussion list led me to believe it was a problem with my Copy’n’Paste. There, piedone states: One remarkable point is a name clashing with content parts: there can't be content parts with the same name in different modules as this leads to problems with schema creation and also when selecting them in them admin menus (because then their displayed name is also the same). This somehow made sense to me, so I went and prefixed the part type name with Teamaton. When that didn’t work I also prefixed all properties of all ContentParts and Records because I remembered that I’d encountered a similar problem before when building our Google Maps module which, contained the same Latitude and Longitude property names that another ContentPart had already defined. But still: to no avail. Desperation. In the first post mentioned above, Bertrand Le Roy also states: I have been in that exact situation. This is probably an error getting swallowed somewhere. […] In my case, it was the feature not enabling all the classes I needed, in particular the record, and the system couldn't find how to map database records. So I went to the Orchard console … feature disable Teamaton.Search … feature enable Teamaton.Search … still nothing. Next it hit me like a sledge hammer – Migrations.cs! I hadn’t taken a single look at the persistence mapping for the SettingPartRecord! Well, turns out there was something wrong in there, but only since after I prefixed both parts and properties because now they wouldn’t match the strings in Migrations.cs anymore (a good example where magic strings break stuff). Kind of helpless, I launched NHProf to look at the database calls that were being made and saw that there weren’t any for the Teamaton.Search module – but for the Orchard.Search module there were … hm. I scanned through the project files again – and stared at placement.info, another file I hadn’t touched since copying the original Search module. Bingo! This was the root of all evil or rather of the search fields not displaying. It looked like this: 1: <Placement> 2: <Place Parts_Search_SiteSettings="Content:1"/> 3: <Place Parts_Search_SearchForm="Content:1"/> 4: </Placement> The problem with it was that I had renamed all the view files and prepended a prefix to them! So the correct version should look like this: 1: <Placement> 2: <Place Parts_TeamatonSearch_SiteSettings="Content:1"/> 3: <Place Parts_TeamatonSearch_SearchForm="Content:1"/> 4: </Placement> That’s because the views are named TeamatonSearch.SiteSettings.cshtml and TeamatonSearch.SearchForm.cshtml and are both placed inside a Parts folder: And now I saw the search fields even for our own new search module. Lesson learned If you can’t see something check the  placement.info  if you (accidentally) haven’t forgot to make that something visible And if you still can’t see it – double check! Happy coding!

About Oliver

shades-of-orange.com code blog logo I build web applications using ASP.NET and have a passion for jQuery. Enjoy MVC 4 and Orchard CMS, and I do TDD whenever I can. I like clean code. Love to spend time with my wife and our daughter. My profile on Stack Exchange, a network of free, community-driven Q&A sites

About Anton

shades-of-orange.com code blog logo I'm a software developer at teamaton. I code in C# and work with MVC, Orchard, SpecFlow, Coypu and NHibernate. I enjoy beach volleyball, board games and Coke.