Rodbourn's Blog http://www.charlesrcook.com/Default.aspx en-US Rodbourn Subtext Version 2.5.2.0 Rodbourn's Blog http://www.charlesrcook.com/images/RSS2Image.gif http://www.charlesrcook.com/Default.aspx 77 60 Migrating an MVC site to Orchard Project 2 (Part 2) Web Programming http://www.charlesrcook.com/archive/2012/12/02/migrating-an-mvc-site-to-orchard-project-2-part-2.aspx <p>I've started migrating my application into the module. The major consideration has been handling the use of LINQ to SQL and the Entity Framework together. </p><ul><li><div>My MVC application uses <a href="http://msdn.microsoft.com/en-us/library/bb386976.aspx">LINQ to SQL</a>. I had to regenerate the data context with sqlmetal to resolve some odd errors when working with NHibernate. In particular my data context was generated by an old version of sqlmetal – it just needed an updated generation. <a href="http://stackoverflow.com/questions/40022/best-way-to-update-linq-to-sql-classes-after-database-schema-change">I found it useful to create a BAT file to regenerate the context for me</a>. </div><p style="margin-left: 36pt"><span style="font-family:Consolas">call "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Tools\VsDevCmd.bat" </span></p><p style="margin-left: 36pt"><span style="font-family:Consolas">sqlmetal /server:MACHINENAME /database:DBNAME /code:DataContext.cs /language:csharp /views /functions /sprocs /namespace:Models /context:DataBase </span></p></li><li><div>I ran into an issue with my <a href="http://geekswithblogs.net/narent/archive/2006/10/09/93544.aspx">'Distributed Transaction Coordinator' service not running</a>. This threw a run time exception during my module development. <span style="text-decoration:line-through">It appears to be needed when my LINQ to SQL context and Orchard's NHibernate context use transactions at the same time.</span> </div><ul><li><strong>The solution was using a new TransactionScope around the LINQ to SQL calls with TransactionScopeOption.Surpress. </strong></li></ul></li><li><div>During the development of a module I needed to uninstall the module from the database. There were two options, I used the later. </div><ul><li><a href="http://www.locked.nl/how-to-fully-remove-a-module-from-orchard">Remove it manually from the database</a>. </li><li><a href="http://stackoverflow.com/questions/11819970/orchard-cms-module-development-workflow">Update the migration</a> to bring it to another revision number and collapse the revisions once development is complete. </li></ul></li><li>I found <a href="http://skywalkersoftwaredevelopment.net/blog/writing-an-orchard-webshop-module-from-scratch-part-4">this tutorial</a> on developing a content part useful. It is detailed and provides another perspective. Yet another useful tutorial in creating a content part <a href="http://www.deepcode.co.uk/2011/05/real-world-orchard-cmspart-6custom.html">is found here</a>. Finally, there is the very basic tutorial on creating a <a href="http://docs.orchardproject.net/Documentation/Writing-a-content-part">map content part</a> which is perhaps the most useful for its minimalism. </li><li>Turning a content part into a widget is straightforward <a href="http://docs.orchardproject.net/Documentation/Writing-a-widget">through the Migration class</a>. </li></ul><p>The next step is for me to migrate my Controllers and Views into the module. Part of this is integrating my authentication within Orchard.</p><img src="http://www.charlesrcook.com/aggbug/86.aspx" width="1" height="1" /> Rodbourn http://www.charlesrcook.com/archive/2012/12/02/migrating-an-mvc-site-to-orchard-project-2-part-2.aspx Sun, 02 Dec 2012 19:55:59 GMT http://www.charlesrcook.com/archive/2012/12/02/migrating-an-mvc-site-to-orchard-project-2-part-2.aspx#feedback 13 http://www.charlesrcook.com/comments/commentRss/86.aspx Crashplan and Volume Shadow Copy Errors (Fixed) http://www.charlesrcook.com/archive/2012/11/14/crashplan-and-volume-shadow-copy-errors-fixed.aspx <p><a href="http://www.crashplan.com/"><img align="left" src="/images/www_charlesrcook_com/111412_2112_Crashplanan1.png" alt="" border="0" /></a>For the longest time I have been logging Volume Shadow Copy (VSS) errors in my Windows Application log every few seconds. I use<a href="http://www.crashplan.com/"> Crashplan</a> to back up my machine online – other than those errors I have been very happy with it. I didn't have much luck trying to fix the error previously and have been living with it until I stumbled upon the fix. </p><p>When cleaning up space on C:\, I noticed the Crashplan cache was consuming a lot of space (9 GB on an SSD in my case). I moved the cache to the backup drive (a 3 TB USB 3 attached disk) and the errors ceased. Surprise! </p><p>If you have a log full of VSS errors try moving your Crashplan cache to another drive. You can change the location by editing the node cachepath in ProgramData\CrashPlan\conf\my.service.xml. In my case I have it on the same drive as the backup destinations (\temp\cache). Be sure to cycle the crash plan service for the change to take. </p><p>  </p><h3>Some useful links on the error </h3><p><a href="http://www.symantec.com/business/support/index?page=content&amp;id=TECH154496">http://www.symantec.com/business/support/index?page=content&amp;id=TECH154496</a> </p><p><a href="http://www.techrepublic.com/blog/window-on-windows/how-do-i-configure-and-use-shadow-copy-in-microsoft-windows/3221">http://www.techrepublic.com/blog/window-on-windows/how-do-i-configure-and-use-shadow-copy-in-microsoft-windows/3221</a> </p><p><a href="http://support.crashplan.com/doku.php/articles/vss#limitations">http://support.crashplan.com/doku.php/articles/vss#limitations</a> </p><p>  </p><h3>The VSS errors which I was receiving: </h3><p>  </p><p><span style="font-family:Consolas">Description: </span></p><p><span style="font-family:Consolas">Volume Shadow Copy Service error: Error calling a routine on the Shadow Copy Provider {b5946137-7b9f-4925-af80-51abd60b20d5}. Routine returned E_INVALIDARG. Routine details GetSnapshot({00000000-0000-0000-0000-000000000000},0000000000358EB0). </span></p><p>  </p><p><span style="font-family:Consolas">Operation:<br /> Get Shadow Copy Properties </span></p><p>  </p><p><span style="font-family:Consolas">Context:<br /> Execution Context: Coordinator </span></p><img src="http://www.charlesrcook.com/aggbug/85.aspx" width="1" height="1" /> Rodbourn http://www.charlesrcook.com/archive/2012/11/14/crashplan-and-volume-shadow-copy-errors-fixed.aspx Wed, 14 Nov 2012 21:12:19 GMT http://www.charlesrcook.com/archive/2012/11/14/crashplan-and-volume-shadow-copy-errors-fixed.aspx#feedback 15 http://www.charlesrcook.com/comments/commentRss/85.aspx Modified False Position Method in C++ Accepting a Function Pointer Technical Computing http://www.charlesrcook.com/archive/2012/11/14/modified-false-position-method-in-c-accepting-a-function-pointer.aspx <p><img align="left" src="/images/www_charlesrcook_com/111412_1632_ModifiedFal1.png" alt="" />The <a href="http://en.wikipedia.org/wiki/False_position_method">modified false position method</a> is fairly straightforward to implement. The method is described in most numerical methods texts in easily translatable pseudo code. The method requires evaluating the function during the solution process, requiring in a naïve implementation hard coding of the function being solved. </p><p>Function pointers can be used to pass a general function to the method, so that one implementation can be used to solve various functions. In particular, member function pointers can be used to root solve a function for one of many independent variables. Consider for example, f(x,a), where you would like to find x such that f(x,a) = 0 for a particular value of a. </p><p>One solution is to define a function g(x) = f(x,a) in a class, using a from a class member, then use the solver to solve g(x)=0. The class is used to contain the fixed independent variables so that a function pointer with one argument can be passed to the solver. </p><p>Being somewhat new to C++ myself, getting this to work took some research into member function pointers. My implementation is included below. To use it, one would, in a class, define a function which has an argument of double and returns a double using member variables to evaluate the function given a particular x. Then in the class create a member function pointer to the function being solved. </p><p>For example one could use the solver in a class "TranscendentalSolver" with a double fTranscendental(double x) member function like so: </p><p>  </p><p style="margin-left: 36pt"><span style="color:blue"><span style="font-family:Consolas; font-size:9pt; background-color:white">double<span style="color:black"> (TranscendentalSolver::*f)(<span style="color:blue">double<span style="color:black">) = &amp;TranscendentalSolver::fTranscendental;</span></span></span></span> </span></p><p style="margin-left: 36pt">  </p><p style="margin-left: 36pt"><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// use a modified false position solver to solve the transcendental<span style="color:black"> </span></span></p><p style="margin-left: 36pt"><span style="color:black"><span style="font-family:Consolas; font-size:9pt; background-color:white">b = ModFalsePos(f, *<span style="color:blue">this<span style="color:black">, xLeft, xRight, 1E-15, 1E-15, 100, verbose);</span></span></span> </span></p><p>  </p><p>My implementation of the modified false position method is listed below. <strong>Note: I modified it to use bisection in the case when the new root is out of bounds (an issue I had solving atan). </strong></p><p>  </p><p><span style="color:blue; font-family:Consolas; font-size:9pt; background-color:white">#ifndef<span style="color:black"> __MODIFIEDFALSEPOSITION_H </span></span></p><p><span style="color:blue; font-family:Consolas; font-size:9pt; background-color:white">#define<span style="color:black"> __MODIFIEDFALSEPOSITION_H </span></span></p><p>  </p><p>  </p><p><span style="color:blue; font-family:Consolas; font-size:9pt; background-color:white">#include<span style="color:black"> <span style="color:#a31515">&lt;cstdio&gt;<span style="color:black"> </span></span></span></span></p><p><span style="color:blue; font-family:Consolas; font-size:9pt; background-color:white">#include<span style="color:black"> <span style="color:#a31515">&lt;math.h&gt;<span style="color:black"> </span></span></span></span></p><p>  </p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">//<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// Modified False Position Method, for details<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// see p 129 in Numerical Methods by Chapra.<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// f - function pointer to the function to find a root<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// xl - lower x bound<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// xu - upper x bound<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// es - relative stopping error<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// et - stopping error (abs(f(xr)) &lt; et)<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// imax - maximum iterations<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// verbose - whether to print information to cout<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">//<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// This is a templated Function so that a member function pointer<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// may be passed. This is very useful when the function has<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// several arguments, but only one is being varied. Then the<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// caller may define a member function, using class members to<span style="color:black"> </span></span></p><p><span style="color:green; font-family:Consolas; font-size:9pt; background-color:white">// find the other parameters.<span style="color:black"> </span></span></p><p><span style="color:blue; font-family:Consolas; font-size:9pt; background-color:white">template<span style="color:black">&lt;<span style="color:blue">typename<span style="color:black"> F&gt; </span></span></span></span></p><p><span style="color:blue; font-family:Consolas; font-size:9pt; background-color:white">double<span style="color:black"> ModFalsePos(<span style="color:blue">double<span style="color:black"> (F::*f)(<span style="color:blue">double<span style="color:black">), F &amp; obj, </span></span></span></span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:blue">double<span style="color:black"> xl, <span style="color:blue">double<span style="color:black"> xu, <span style="color:blue">double<span style="color:black"> es, <span style="color:blue">double<span style="color:black"> et, <span style="color:blue">int<span style="color:black"> imax, </span></span></span></span></span></span></span></span></span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:blue">bool<span style="color:black"> verbose) </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">{ </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:green">// the current iteration<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:blue">int<span style="color:black"> iter = 0; </span></span></span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:green">// lower and upper iteration counts,<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:green">// used to detect when one of the bounds<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:green">// is 'stuck'.<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:blue">int<span style="color:black"> il = 0; </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:blue">int<span style="color:black"> iu = 0; </span></span></span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:green">// the current root<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:blue">double<span style="color:black"> xr = 0; </span></span></span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:green">// the current error estimate<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:blue">double<span style="color:black"> ea = 0; </span></span></span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:green">// the lower function value<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:blue">double<span style="color:black"> fl = (obj.*f)(xl); </span></span></span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:green">// the upper function value<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:blue">double<span style="color:black"> fu = (obj.*f)(xu); </span></span></span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:blue">if<span style="color:black"> (verbose) </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    { </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        printf(<span style="color:#a31515">"xl = %12.4e, xu = %12.4e\n"<span style="color:black">, xl, xu); </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        printf(<span style="color:#a31515">"%6s%12s%12s%12s%12s%12s\n"<span style="color:black">, </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">                <span style="color:#a31515">"Iter."<span style="color:black">, <span style="color:#a31515">"x_l"<span style="color:black">, <span style="color:#a31515">"x_u"<span style="color:black">, <span style="color:#a31515">"x_r"<span style="color:black">, <span style="color:#a31515">"f(x_r)"<span style="color:black">, <span style="color:#a31515">"ea"<span style="color:black">); </span></span></span></span></span></span></span></span></span></span></span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    } </span></p><p>  </p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:blue">while<span style="color:black">(<span style="color:blue">true<span style="color:black">) </span></span></span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    { </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:green">// new root estimate and function value<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:blue">double<span style="color:black"> xrold = xr; </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        xr = xu - fu * (xl - xu) / (fl - fu); </span></p><p>  </p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:green">// if out of bounds - false position<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:green">// has failed, use bisection<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:blue">if<span style="color:black"> ( xr &gt; xu || xr &lt; xl ) </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        { </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            xr = (xl+xu)/2; </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        } </span></p><p>  </p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:blue">double<span style="color:black"> fr = (obj.*f)(xr); </span></span></span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:green">// iteration counter increment<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        iter += 1; </span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:green">// error estimate (relative)<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:blue">if<span style="color:black"> (xr != 0 ) </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            ea = std::abs((xr-xrold)/xr)*100; </span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:green">// test signs<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:blue">double<span style="color:black"> test = fl*fr; </span></span></span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:blue">if<span style="color:black"> (test &lt; 0) </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        { </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            xu = xr; </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            fu = (obj.*f)(xu); </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            iu = 0; </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            il += 1; </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            <span style="color:blue">if<span style="color:black"> (il &gt;= 2) </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">                fl = fl / 2; </span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        } </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:blue">else<span style="color:black"> <span style="color:blue">if<span style="color:black"> (test &gt; 0) </span></span></span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        { </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            xl = xr; </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            fl = (obj.*f)(xl); </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            il = 0; </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            iu += 1; </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            <span style="color:blue">if<span style="color:black"> (iu &gt;= 2) </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">                fu = fu /2; </span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        } </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:blue">else<span style="color:black"> </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        { </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            ea = 0; </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        } </span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:blue">if<span style="color:black">(verbose) </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        { </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            printf(<span style="color:#a31515">"%6i%12.4e%12.4e%12.4e%12.4e%12.4e\n"<span style="color:black">, </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">                    iter, xl, xu, xr, fr, ea); </span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        } </span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">        <span style="color:blue">if<span style="color:black"> (ea &lt; es || std::abs(fr) &lt; et || iter &gt;= imax) </span></span></span></p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">            <span style="color:blue">break<span style="color:black">; </span></span></span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    } </span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">    <span style="color:blue">return<span style="color:black"> xr; </span></span></span></p><p>  </p><p><span style="color:black; font-family:Consolas; font-size:9pt; background-color:white">} </span></p><p>  </p><p><span style="color:blue; font-family:Consolas; font-size:9pt; background-color:white">#endif<span style="color:black"> </span></span></p><img src="http://www.charlesrcook.com/aggbug/84.aspx" width="1" height="1" /> Rodbourn http://www.charlesrcook.com/archive/2012/11/14/modified-false-position-method-in-c-accepting-a-function-pointer.aspx Wed, 14 Nov 2012 16:32:42 GMT http://www.charlesrcook.com/archive/2012/11/14/modified-false-position-method-in-c-accepting-a-function-pointer.aspx#feedback http://www.charlesrcook.com/comments/commentRss/84.aspx Migrating an MVC site to Orchard Project (Part 1) Web Programming http://www.charlesrcook.com/archive/2012/11/11/migrating-an-mvc-site-to-orchard-project-part-1.aspx <p><img align="left" src="/images/www_charlesrcook_com/111112_2151_Migratingan1.jpg" alt="" />I have been moving an <a href="http://www.asp.net/mvc">asp.net MVC</a> web site of mine to the <a href="http://orchardproject.net/">Orchard Project</a>. As a developer I love working with MVC, however, I had not found a nice solution for content management. All of the solutions were too intrusive, tainting the MVC flavor of the site, or rather young projects I didn't want to invest in. A recent survey of <a href="http://en.wikipedia.org/wiki/Content_management_system">Content Management System</a> (CMS) solutions found me looking right at the <a href="http://en.wikipedia.org/wiki/Orchard_Project">Orchard Project</a>. </p><p>The project is not 'light', but it is very elegant. The project uses the '<a href="http://channel9.msdn.com/Events/MIX/MIX11/FRM02">MS Web Stack of love</a>' which plays very nicely with my current MVC solution. Most important, at least to me, is that it has a bunch of <a href="http://orchardproject.net/about">really smart and dedicated people behind it</a>, allowing me to learn and adopt some really great ideas while migrating. </p><p>Actually migrating the site has been a huge learning experience for me – I'm finding much of my knowledge of open source projects to be circa 2008/2009. There are a lot of ideas to absorb in the project, but they are good ideas. Some key points that would have helped me along with the integration. </p><ul><li>I started with the source distribution of Orchard, unzipped it into a new location configured as a new website in IIS. From there I worked with the Visual Studio solution in the site root. I followed this guide: <a href="http://docs.orchardproject.net/Documentation/Manually-installing-Orchard-zip-file">http://docs.orchardproject.net/Documentation/Manually-installing-Orchard-zip-file</a>, but note the download link in the guide is old – use: <a href="http://orchard.codeplex.com/releases/view/90325">http://orchard.codeplex.com/releases/view/90325</a> (or the newer download if 1.6 is old) </li><li>Orchard is extensible through modules, each of which is like its own MVC project. In my case it made sense to bring my existing MVC site into an orchard module. <a href="http://stackoverflow.com/questions/5269170/integrate-existing-asp-net-mvc-application-with-orchard-cms">http://stackoverflow.com/questions/5269170/integrate-existing-asp-net-mvc-application-with-orchard-cms</a> </li><li>Orchard uses the <a href="http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx">Razor view engine</a> (you don't have – but I found it easier to, even though I am new to Razor). For me a big step in the migration was moving to Razor and cleaning up the Html. </li><li>Orchard uses Themes to control the look of the site. Thus, I migrated my masterpage(s)/design into a new Theme. <a href="http://docs.orchardproject.net/Documentation/Anatomy-of-a-theme">http://docs.orchardproject.net/Documentation/Anatomy-of-a-theme</a>, <a href="http://www.deepcode.co.uk/2011/05/real-world-orchard-cms-part-2-creating.html">http://www.deepcode.co.uk/2011/05/real-world-orchard-cms-part-2-creating.html</a> </li><li>Orchard allows for 'overloading' shapes/widgets (a 'view') through the Theme. If you want to redefine how the footer widget is rendered, for example, you would place a new Widget-Footer.cshtml in your Theme root. This definition would then override the default Orchard implementation. Similarly, to control the rendering of the Html Document, create your own Document.cshtml in the Theme. I found I was doing this a fair amount to control the output of my Theme. </li><li>Orchard also allows for 'Alternate' variations of shapes depending on the URL, for example. I used this to define an alternate Layout-homepage.cshtml to give my home page a different definition. Note you do have to install the <a href="http://docs.orchardproject.net/Documentation/Customizing-Orchard-using-Designer-Helper-Tools">Designer Helper Tools module</a> for this too work (That stumped me for a bit) <a href="http://docs.orchardproject.net/Documentation/Alternates">http://docs.orchardproject.net/Documentation/Alternates</a> </li><li>When creating new 'Widgets' to serve as content regions, I found the wrapping with a div element and rendering the widget title in a header tag undesirable. I only wanted the Html Content of the widget rendered, not the extra wrapping tags. To remove the wrapping I added to the top of my widget "<span style="color:black; font-family:Consolas; font-size:9pt"><span style="background-color:yellow">@{</span><span style="background-color:white"> Model.Metadata.Wrappers.Clear(); </span><span style="background-color:yellow">}</span></span>", which prevented any Html being rendered around the widget. There's probably a better way to do this that I haven't found, though. </li></ul><p>Currently I am migrating my MVC site into a module now that the Theme migration is complete. </p><img src="http://www.charlesrcook.com/aggbug/83.aspx" width="1" height="1" /> Rodbourn http://www.charlesrcook.com/archive/2012/11/11/migrating-an-mvc-site-to-orchard-project-part-1.aspx Sun, 11 Nov 2012 21:51:37 GMT http://www.charlesrcook.com/archive/2012/11/11/migrating-an-mvc-site-to-orchard-project-part-1.aspx#feedback 2 http://www.charlesrcook.com/comments/commentRss/83.aspx Getting rid of an ants nest in a parked car http://www.charlesrcook.com/archive/2012/09/23/getting-rid-of-an-ants-nest-in-a-parked-car.aspx <p>I keep my car parked outside with a car cover on it and move it about every two weeks. This seems to have made it an ideal home for ants, even though there is nothing they could eat in there. They seem to have decided it's a great home, and to just bring their food to the nest in the trunk… </p><p>I put the car cover in the trunk running errands one day, nothing out of the ordinary. When I was home and took the cover out of the trunk I noticed a whole swarm of ants migrating to the car cover… Apparently they decided the car cover was slightly better than the trunk and were moving. </p><p>I tried a <a href="http://www.orkin.com/ask-the-orkin-man/get-rid-ants-in-car/" target="_blank">few ant baits as suggested</a>, but what really worked was <strong>gel bait that you spray</strong>. It lasts up to a year and lets you place 'lines' which the ants cannot cross. "Raid Max Bug Barrier" did the trick for me – I'm sure others make similar products. </p><p>I laid a barrier around each tire, by drawing a circle with the gel around it. The idea was to keep them from being able to go out and get more food, or at least kill them on the way. I wouldn't suggest spraying the bait on the tire itself as <a href="http://www.ehow.com/how_4488363_get-rid-ants-car.html" target="_blank">ehow suggests</a> – it might damage the rubber. </p><p>I also lifted the carpet in a few locations in the car and sprayed a line of the gel. Again avoid putting the gel on something it might damage, such as the carpet. Surprisingly, the next day the ants were dead. No more roaming ants around the cabin either. Now, to keep the roaming dogs away from the cover…</p><img src="http://www.charlesrcook.com/aggbug/82.aspx" width="1" height="1" /> Rodbourn http://www.charlesrcook.com/archive/2012/09/23/getting-rid-of-an-ants-nest-in-a-parked-car.aspx Sun, 23 Sep 2012 15:42:51 GMT http://www.charlesrcook.com/archive/2012/09/23/getting-rid-of-an-ants-nest-in-a-parked-car.aspx#feedback 3 http://www.charlesrcook.com/comments/commentRss/82.aspx Normal Shock T-s Diagram http://www.charlesrcook.com/archive/2012/09/15/normal-shock-t-s-diagram.aspx <p>A <a href="http://en.wikipedia.org/wiki/Fanno_flow" target="_blank">Fanno Flow</a> line on a <a href="http://en.wikipedia.org/wiki/Temperature%E2%80%93entropy_diagram" target="_blank">T-s diagram</a> is developed using the continuity and energy equations. A <a href="http://en.wikipedia.org/wiki/Rayleigh_flow" target="_blank">Rayleigh Flow</a> line on a T-s diagram on the other hand is developed using the continuity and momentum equations. A solution to both a Fanno Flow and Rayleigh Flow is the same as solving continuity, momentum and energy, which are used in solving Normal Shocks. </p><p>A Normal Shock can then be seen as the intersection of both a Fanno line and Rayleigh line on a T-s diagram. In moving from state 1 to a second state 2 on a Rayleigh line there are several possible paths as shown below. While both ending states have the same Mach number, each path requires different amounts of energy (heat transfer into the flow), seen as the area under the curve on a T-s diagram. In the examples of the figure, path 5 requires the least heat and path 1 requires the most heat addition. </p><p>In creating the T-s Diagram below, all of the flows share the same reference temperature, the temperature at state 1. The entropy changes were shifted so that all the curves have zero entropy generation at state 1. The Diagram below is my own original work. </p><p>  </p><p><img src="/images/www_charlesrcook_com/091512_1644_NormalShock1.png" alt="" /></p><img src="http://www.charlesrcook.com/aggbug/81.aspx" width="1" height="1" /> Rodbourn http://www.charlesrcook.com/archive/2012/09/15/normal-shock-t-s-diagram.aspx Sat, 15 Sep 2012 16:44:23 GMT http://www.charlesrcook.com/archive/2012/09/15/normal-shock-t-s-diagram.aspx#feedback 1 http://www.charlesrcook.com/comments/commentRss/81.aspx MediaWiki IIS7 Output Caching and Friendly/Short URLs http://www.charlesrcook.com/archive/2012/09/12/mediawiki-iis7-output-caching-and-friendlyshort-urls.aspx <p>MediaWiki has been running painfully slow for me out of the box and the solution, as it always seems to be, was to enable caching. </p><p>I first enabled caching within MediaWiki, but this only helped… a little. I did this first step within LocalSettings.php </p><p style="margin-left: 36pt"><span style="font-family:Consolas"><span style="color:#002060">$wgCacheDirectory</span> = <span style="color:#00b050">"c:\your\path\to\cache"</span>;<br /><span style="color:#002060">$wgFileCacheDirectory </span>= <span style="color:#00b050">"c:\your\path\to\cache "</span>;<br /><span style="color:#002060">$wgEnableSidebarCache </span>= <span style="color:#984806">true</span>;<br /><span style="color:#002060">$wgUseFileCache </span>= <span style="color:#984806">true</span>;<br /><span style="color:#002060">$wgShowIPinHeader </span>= <span style="color:#984806">false</span>;<br /><span style="color:#002060">$wgEnableParserCache </span>= <span style="color:#984806">true</span>;<br /><span style="color:#002060">$wgCachePages </span>= <span style="color:#984806">true</span>;<br /><br /><span style="color:#002060">$wgMainCacheType </span>= CACHE_ACCEL;<br /><span style="color:#002060">$wgMessageCacheType </span>= CACHE_ACCEL;<br /><span style="color:#002060">$wgParserCacheType </span>= CACHE_ACCEL;<br /><span style="color:#002060">$wgMemCachedServers </span>= <span style="color:#984806">array</span>(); </span></p><p>Using Chrome's Developer Tools, particularly the network tool where each request is shown, I noticed almost all of the time was spent in loading <span style="font-family:Consolas">load.php</span>! The result was correctly being cached at the application level, with 304 Not Modified responses, but it was taking a couple of seconds to return that response. With a dozen or so resources to load (CSS/JS) this accumulates to half minute load times quickly… Something internal to MediaWiki was painfully slow. But the content returned by <span style="font-family:Consolas">load.php</span> is just static resource; just cache it at the server level. </p><p>Using the IIS GUI here will lead you into a trap – or at least it lead me into one. The GUI tends to convert "*.php" into ".php" extensions, which don't match. So, using your favorite editor add a caching entry into Web.config for the MediaWiki site. Here I chose ten minute cache timeouts. </p><p>  </p><p><span style="color:blue; font-family:Consolas; font-size:9pt; background-color:white"> &lt;<span style="color:#a31515">caching<span style="color:blue">&gt;<span style="color:black"> </span></span></span></span></p><p><span style="color:blue; font-family:Consolas; font-size:9pt; background-color:white"> &lt;<span style="color:#a31515">profiles<span style="color:blue">&gt;<span style="color:black"> </span></span></span></span></p><p><span style="color:blue; font-family:Consolas; font-size:9pt; background-color:white"> &lt;<span style="color:#a31515">add<span style="color:blue"> <span style="color:red">extension<span style="color:blue">=<span style="color:black">"<span style="color:blue">*.php5<span style="color:black">"<span style="color:blue"> <span style="color:red">policy<span style="color:blue">=<span style="color:black">"<span style="color:blue">CacheUntilChange<span style="color:black">"<span style="color:blue"> <span style="color:red">kernelCachePolicy<span style="color:blue">=<span style="color:black">"<span style="color:blue">CacheUntilChange<span style="color:black">"<span style="color:blue"> <span style="color:red">duration<span style="color:blue">=<span style="color:black">"<span style="color:blue">00:10:30<span style="color:black">"<span style="color:blue"> <span style="color:red">varyByQueryString<span style="color:blue">=<span style="color:black">"<span style="color:blue">*<span style="color:black">"<span style="color:blue"> /&gt;<span style="color:black"> </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p><p><span style="color:blue; font-family:Consolas; font-size:9pt; background-color:white"> &lt;<span style="color:#a31515">add<span style="color:blue"> <span style="color:red">extension<span style="color:blue">=<span style="color:black">"<span style="color:blue">*.php<span style="color:black">"<span style="color:blue"> <span style="color:red">policy<span style="color:blue">=<span style="color:black">"<span style="color:blue">CacheUntilChange<span style="color:black">"<span style="color:blue"> <span style="color:red">kernelCachePolicy<span style="color:blue">=<span style="color:black">"<span style="color:blue">CacheUntilChange<span style="color:black">"<span style="color:blue"> <span style="color:red">duration<span style="color:blue">=<span style="color:black">"<span style="color:blue">00:10:30<span style="color:black">"<span style="color:blue"> <span style="color:red">varyByQueryString<span style="color:blue">=<span style="color:black">"<span style="color:blue">*<span style="color:black">"<span style="color:blue"> /&gt;<span style="color:black"> </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p><p><span style="color:blue; font-family:Consolas; font-size:9pt; background-color:white"> &lt;/<span style="color:#a31515">profiles<span style="color:blue">&gt;<span style="color:black"> </span></span></span></span></p><p><span style="color:blue"><span style="font-family:Consolas; font-size:9pt; background-color:white"> &lt;/<span style="color:#a31515">caching<span style="color:blue">&gt;</span></span></span> </span></p><p>And hopefully that should do it, after the first few calls to <span style="font-family:Consolas">load.php</span> the responses should be speedily cached. Note you may want to vary by header as well if you want to simply send 304 responses with no content to save bandwidth by using browser cache. My particular application is on an intranet. </p><p>  </p><h1>Note on browsing speed </h1><p>My installation of MediaWiki is loading about ten resources. Most browsers support 6 concurrent requests (hits to load.php), see <a href="http://www.browserscope.org/?category=network" target="_blank">http://www.browserscope.org/?category=network</a>. This means that the page load would have to wait for load.php twice, rather than ten times in parallel. With Firefox and IE the number of simultaneous requests can be increased, reducing the load time further, see <a href="http://gnoted.com/3-hacks-for-firefox-double-internet-browsing-speed/" target="_blank">http://gnoted.com/3-hacks-for-firefox-double-internet-browsing-speed/</a>. </p><p>This shaves a couple seconds off of a fresh load (where the cache is empty). </p><p>  </p><p>  </p><p>  </p><p>  </p><p>  </p><p>  </p><p>  </p><img src="http://www.charlesrcook.com/aggbug/80.aspx" width="1" height="1" /> Rodbourn http://www.charlesrcook.com/archive/2012/09/12/mediawiki-iis7-output-caching-and-friendlyshort-urls.aspx Wed, 12 Sep 2012 19:07:47 GMT http://www.charlesrcook.com/archive/2012/09/12/mediawiki-iis7-output-caching-and-friendlyshort-urls.aspx#feedback 2 http://www.charlesrcook.com/comments/commentRss/80.aspx BibTex Citation Management in MediaWiki http://www.charlesrcook.com/archive/2012/09/05/bibtex-citation-management-in-mediawiki.aspx <p>Lately I have been setting up a local MediaWiki installation to organize and document my research (see previous posts which relate to installing MediaWiki on Windows). An essential feature is of course documentation, and <a href="http://www.nise81.com/archives/816" target="_blank">nise presents a nice solution</a> by combining two extensions, <a href="http://openwetware.org/wiki/Wikiomics:Biblio" target="_blank">Biblio</a> and <a href="http://www.mediawiki.org/wiki/Extension:Bibtex" target="_blank">Bibtex</a>. </p><p>This solution allows you to use the BibTex citations from a manager such as <a href="http://www.mendeley.com/" target="_blank">Mendeley</a> or <a href="http://jabref.sourceforge.net/" target="_blank">JabRef</a> in both the MediaWiki citations and LaTex citations. </p><p>I integrated the two similarly to how <a href="http://www.nise81.com/archives/816" target="_blank">nise</a> has, but with a modification on matching Bibtex entries, using a regular expression instead of a string match. </p><ol><li>Install <a href="http://openwetware.org/wiki/Wikiomics:Biblio" target="_blank">Biblio</a> and <a href="http://www.mediawiki.org/wiki/Extension:Bibtex" target="_blank">Bibtex</a> extensions </li><li>Open Biblio.php and location the function render_biblio </li><li><div>Define the following within the function (just under the two global's works) </div><p style="margin-left: 36pt">  </p><p style="margin-left: 36pt"><span style="font-family:Consolas"><span style="color:#1f497d">$bibtexx</span> = <span style="color:#984806">new </span>BibTex<span style="color:#7030a0">()</span>; </span></p></li><li><div>Find "<span style="color:#1f497d"><span style="font-family:Consolas; font-size:9pt; background-color:white">$text<span style="color:#333333"> = <span style="color:#1f497d">$this<span style="color:#7030a0">-&gt;<span style="color:#333333">get<span style="color:#7030a0">(<span style="color:#1f497d">$ref<span style="color:#7030a0">,<span style="color:#333333"> <span style="color:#00b050">'text'<span style="color:#7030a0">);</span></span></span></span></span></span></span></span></span></span></span>" <span style="color:black">further down in the function and add the following just below it.</span> </span></div><p style="margin-left: 36pt">  </p><p style="margin-left: 72pt"><span style="color:#984806; font-family:Consolas">if<span style="color:#7030a0">(</span>preg_match<span style="color:#7030a0">(<span style="color:#00b050">"/@[a-zA-Z]+/"<span style="color:#7030a0">,</span> <span style="color:#1f497d">$text<span style="color:#7030a0">,</span> $matches<span style="color:#7030a0">)){</span><br /></span> <span style="color:#1f497d">$bibtexx<span style="color:#7030a0">-&gt;</span>BibTex($text<span style="color:#7030a0">);</span><br /></span> <span style="color:#1f497d">$text <span style="color:#7030a0">=</span> $bibtexx<span style="color:#7030a0">-&gt;</span>html<span style="color:#7030a0">();</span><br /><span style="color:#7030a0">}</span> </span></span></span></span></p></li><li><div>The example by <a href="http://www.nise81.com/archives/816" target="_blank">nise</a> will now work as intended </div><p style="margin-left: 36pt">  </p><p style="margin-left: 36pt"><span style="font-family:Consolas">#localref local reference<br />#[[Literature]]<br />#somebook @book{Alexander1979,<br />    Author = {Christopher Alexander},<br />    Publisher = {Oxford University Press},<br />    Title = {The Timeless Way of Building},<br />    Year = {1979}}<br />#someusualbook MySelf. "Me Myself and I". Self.<br />#x ... </span></p></li></ol><p>The difference with what was originally done is the Regular Expression match. Since a BibTex entry starts with @type, we test for @[someword]. </p><p>  </p><p>  </p><p>  </p><p>  </p><img src="http://www.charlesrcook.com/aggbug/79.aspx" width="1" height="1" /> Rodbourn http://www.charlesrcook.com/archive/2012/09/05/bibtex-citation-management-in-mediawiki.aspx Wed, 05 Sep 2012 14:21:04 GMT http://www.charlesrcook.com/archive/2012/09/05/bibtex-citation-management-in-mediawiki.aspx#feedback 1 http://www.charlesrcook.com/comments/commentRss/79.aspx How to export Excel plots to a vector image (EPS, EMF, SVG, etc.) http://www.charlesrcook.com/archive/2012/08/31/how-to-export-excel-plots-to-a-vector-image-eps.aspx <p>This is a bit of a workaround, but it's the only way I know of to export an Excel plot into a vector format such as EPS or EMF. In my case I needed to export the plot to EPS for inclusion within a LaTeX document. </p><ol><li>Create the plot in Excel </li><li>Copy the plot and paste it into a new, empty word document. </li><li>Save the word document as a PDF. When word exports to PDF it embeds the plot in vector form. </li><li>Using <a href="http://inkscape.org/">Inkscape</a>, import the PDF </li><li>In Inkscape, File -&gt; Document Properties -&gt; Resize page to content… -&gt; Resize page to drawing or selection </li><li>File -&gt; Save as -&gt; </li><li>Select the format you want, SVG, PS, EPS, etc. </li></ol><p>And there you have it, publication quality plots from Excel. </p><p>Keep in mind that your data values may be extracted through the vector image by someone doing a similar process with your image, i.e., opening it in Inkscape and pulling data points out. It's even worse when you send a plot in a word document; you can often recover the original Excel sheet, including your calculations (not just data!)</p><img src="http://www.charlesrcook.com/aggbug/78.aspx" width="1" height="1" /> Rodbourn http://www.charlesrcook.com/archive/2012/08/31/how-to-export-excel-plots-to-a-vector-image-eps.aspx Fri, 31 Aug 2012 14:39:33 GMT http://www.charlesrcook.com/archive/2012/08/31/how-to-export-excel-plots-to-a-vector-image-eps.aspx#feedback 5 http://www.charlesrcook.com/comments/commentRss/78.aspx MediaWiki Short URLs with IIS 7 and Subpages http://www.charlesrcook.com/archive/2012/08/28/mediawiki-short-urls-with-iis-7-and-subpages.aspx <p>Following the guide on <a href="http://www.mediawiki.org/wiki/Manual:Short_URL/wiki/Page_title_--_Windows_with_IIS7--root_access">mediawiki.org</a> got me 99% there with nice short URLs on Windows with IIS 7. </p><p>One small hiccup, creating subpages of the form </p><p style="margin-left: 36pt"><span style="color:#1f497d; font-family:Consolas">wiki/PageTitle/SubPageTitle </span></p><p>The suggested Regular Expression provided by URL Rewrite needs a simple update. </p><p style="margin-left: 36pt"><span style="color:#c0504d; font-family:Consolas">&lt;match url="^([^/]+)/?$" /&gt; </span></p><p>Should be </p><p style="margin-left: 36pt"><span style="color:#c0504d; font-family:Consolas">&lt;match url="^([^/]+.+?)/*$" /&gt; </span></p><p>Or, as is done in the guide, with the wiki path </p><p style="margin-left: 36pt"><span style="color:#c0504d; font-family:Consolas">&lt;match url="^(wiki/[^/]+.+?)/*$" /&gt; </span></p><p>Understanding the change requires reading the original regular expression. </p><ul><li>"<span style="color:#c0504d; font-family:Consolas">^</span>" Match from the start of the string </li><li>"<span style="color:#c0504d; font-family:Consolas">[^/]</span>" Here "<span style="color:#c0504d; font-family:Consolas">^</span>" has a special meaning, it negates "<span style="color:#c0504d; font-family:Consolas">/</span>" so that this matches any character but "<span style="color:#c0504d; font-family:Consolas">/</span>" </li><li>"<span style="color:#c0504d; font-family:Consolas">[^/]+</span>" The plus means to match at least once or more </li><li>"<span style="color:#c0504d; font-family:Consolas">([^/]+)</span>" The parenthesis are simply a grouping, so that what's matched inside is the available as the 'first match'. Put another way this selects the output from the pattern match. "<span style="color:#c0504d; font-family:Consolas">{R:1}</span>" is actually this value being used. </li><li>"<span style="color:#c0504d; font-family:Consolas">/?</span>" Matches none to one "<span style="color:#c0504d; font-family:Consolas">/</span>" non-greedily (more on that). </li><li>"<span style="color:#c0504d; font-family:Consolas">$</span>" Matches the end of the string </li></ul><p>We would like it to match a title with "<span style="color:#c0504d; font-family:Consolas">/</span>" within it. MediaWiki will handle the details of splitting the title into subpages. We are already matching anything but "<span style="color:#c0504d; font-family:Consolas">/</span>", so we might as well match anything. In RegEx, a "<span style="color:#c0504d; font-family:Consolas">.</span>" means just about anything (anything but a new line). We still don't want to start a title with "<span style="color:#c0504d; font-family:Consolas">/</span>", so after the first non "<span style="color:#c0504d; font-family:Consolas">/</span>" matches, lets accept anything up until the end of the string. We do that by simply inserting "<span style="color:#c0504d; font-family:Consolas">.+</span>", matching one or more of anything but a new line. </p><p>As you might have noticed, the new patterns have two other changes, an additional "<span style="color:#c0504d; font-family:Consolas">?</span>" and replacing the last "<span style="color:#c0504d; font-family:Consolas">?</span>" with "<span style="color:#c0504d; font-family:Consolas">*</span>" at the end of the pattern. Why gets into something called greedy and non-greedy matching. Consider the following path </p><p style="margin-left: 36pt"><span style="color:#1f497d; font-family:Consolas">wiki/PageTitle/SubPageTitle/ </span></p><p>Where should the trailing "<span style="color:#c0504d; font-family:Consolas">/</span>" go? Should it be part of the title or matched as an optional end of the path, but not part of the title? The title should be "<span style="color:#1f497d; font-family:Consolas">PageTitle/SubPageTitle</span>" and not "<span style="color:#1f497d; font-family:Consolas">PageTitle/SubPageTitle/</span>", but the title matching, "<span style="color:#c0504d; font-family:Consolas">([^/]+.+)</span>" and the trailing "<span style="color:#c0504d; font-family:Consolas">/</span>" matching "<span style="color:#c0504d; font-family:Consolas">/?</span>" both may match the ending "<span style="color:#c0504d; font-family:Consolas">/</span>". </p><p>What we do is add a "<span style="color:#c0504d; font-family:Consolas">?</span>" just after the "<span style="color:#c0504d; font-family:Consolas">+</span>" to match non-greedily. When this is done, the pattern will match as short of a pattern as possible. But, we now need the trailing "<span style="color:#c0504d; font-family:Consolas">/</span>" to match greedily. We can do this easily by changing the "<span style="color:#c0504d; font-family:Consolas">?</span>" to "<span style="color:#c0504d; font-family:Consolas">*</span>" which will greedily matching zero or more trailing "<span style="color:#c0504d; font-family:Consolas">/</span>". </p><p>And there you have it, subpage support.</p><img src="http://www.charlesrcook.com/aggbug/77.aspx" width="1" height="1" /> Rodbourn http://www.charlesrcook.com/archive/2012/08/28/mediawiki-short-urls-with-iis-7-and-subpages.aspx Tue, 28 Aug 2012 08:21:45 GMT http://www.charlesrcook.com/archive/2012/08/28/mediawiki-short-urls-with-iis-7-and-subpages.aspx#feedback 1 http://www.charlesrcook.com/comments/commentRss/77.aspx