ASP.NET MVC and ReturnUrl

I’ve seen many ASP.NET MVC samples and some of them do not honor de ReturnUrl parameter, rendering this unusable.

Classic ASP.NET has the login form component that puts the same exact URL used to access the login page in the form action URL, preserving the ReturnUrl parameter and then, FormsAuthentication.GetReturnUrl() gets it from the Request.QueryString collection.

Fortunately, the GetReturnUrl() method looks as well in Request.Form in case there’s nothing in the query, this way, we can use a hidden field as well to store the ReturnUrl in the View and pass it through POST when the login form is submitted.

So, in ASP.NET MVC we have two options:

  1. Use simply Html.BeginForm() without parameters, which will put a simple form tag, with the same URL as the current one and use POST by default
  2. If we want to have more control on the Html.BeginForm(), put a hidden field with the value of the ReturnUrl, only if the ReturnUrl is not empty, or it will fail. This can be obtained from the Request.QueryString collection, the ViewData if we put it previously on the Controller action or even better store it in the ViewModel and have a strong typed reference.

And that’s it. Then, FormsAuthentication.GetReturnUrl() will get the proper URL and other methods like FormsAuthentication.RedirectFromLoginPage() will also work seamlessly.

NHibernate Validator custom messages

After an interesting thread in nhusers, I wrote this is a small post explaining how you can create a simple interpolator for NHibernate Validator that replaces the default messages for your customized ones and as well treats messages for your custom validators. Everything with internationalization using resources.

The first part is to create your own interpolator:

    using System.Globalization;
    using System.Reflection;
    using System.Resources;
    using NHibernate.Validator.Engine;

    public class CustomMessageInterpolator : IMessageInterpolator
    {
        private readonly string ResourceBaseName = "Project.Properties.Validator";

        private readonly ResourceManager resMan;

        public CustomMessageInterpolator()
        {
            this.resMan = new ResourceManager(this.ResourceBaseName, Assembly.GetExecutingAssembly());
        }

        public string Interpolate(string message, IValidator validator, IMessageInterpolator defaultInterpolator)
        {
            var s = GetMessage(message);

            return defaultInterpolator.Interpolate(s, validator, defaultInterpolator);
        }

        private string GetMessage(string message)
        {
            // It's a tempate
            if (!message.StartsWith("{") && !message.EndsWith("}"))
            {
                return message;
            }

            var resource = message.Substring(1, message.Length - 2);

            var m = this.resMan.GetString(resource, CultureInfo.CurrentCulture);

            if (string.IsNullOrEmpty(m))
            {
                // Returns the original message
                return message;
            }

            return m;
        }
    }

I use the same notation as the original project, putting the resource name between { and }. I try to get the string from Validator.resx in the Properties folder of the project and if not found I return the original message. This way, you can override the default messages with your own ones only if you want.

At the end, all messages are passed to the defaultInterpolator, that manages the rest of the substitutions (for example {Max} and {Min} are replaced by the attribute values).

Finally, you have to configure the interpolator in the .config file (it only worked for me in App.config, not in nhvalidator.cfg.xml):

<configuration>
  <configSections>
    <section name="nhv-configuration" type="NHibernate.Validator.Cfg.ConfigurationSectionHandler, NHibernate.Validator" />
  <nhv-configuration xmlns="urn:nhv-configuration-1.0">
    <property name="message_interpolator_class">Project.Validation.CustomMessageInterpolator, Project.Validation</property>
    <mapping assembly="Project.Domain" />
  </nhv-configuration>
  </configSections>
</configuration>

And that’s it. I hope it helps.

NHibernate Burrow and NHibernate Search

Spanish version

In this post I’m going to explain how I managed to make these projects to work together using NHibernate events instead of the classic interceptors. Through these events, we tell NHibernate.Search to index the elements marked for that purpose without touching the session. We only need to get it in order to perform a search in the index and we get it from NHibernate.Burrow.
The first thing we need is to configure the application properly (App.config):

<?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?>
<configuration>
  <configSections>
    <section name=&quot;NHibernate.Burrow&quot; type=&quot;NHibernate.Burrow.Configuration.NHibernateBurrowCfgSection, NHibernate.Burrow&quot; />
    <section name=&quot;nhs-configuration&quot; type=&quot;NHibernate.Search.Cfg.ConfigurationSectionHandler, NHibernate.Search&quot; />
  </configSections>
  <NHibernate.Burrow>
<persistenceUnits>
      <add name=&quot;PersistenceUnit1&quot;
           nh-config-file=&quot;hibernate.cfg.xml&quot; />
    </persistenceUnits>
  </NHibernate.Burrow>

  <nhs-configuration xmlns='urn:nhs-configuration-1.0'>
    <search-factory>
<property name='hibernate.search.default.directory_provider'>NHibernate.Search.Store.RAMDirectoryProvider, NHibernate.Search</property>
<property name='hibernate.search.default.indexBase'>~/Index</property>
    </search-factory>
  </nhs-configuration>
</configuration>

NHibernate.Search does not manage the configuration section properly, so it looks for a section called nhs-configuration, so don’t change the name. On the other side, we should provide a valid hibernate.cfg.xml with NHibernate configuration. For example, for testing you can use an in-memory SQLite database:

<?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?>
<hibernate-configuration xmlns=&quot;urn:nhibernate-configuration-2.2&quot;>
  <session-factory>
<property name=&quot;connection.provider&quot;>NHibernate.Connection.DriverConnectionProvider</property>
<property name=&quot;dialect&quot;>NHibernate.Dialect.SQLiteDialect</property>
<property name=&quot;connection.driver_class&quot;>NHibernate.Driver.SQLite20Driver</property>
<property name=&quot;connection.connection_string&quot;>Data Source=:memory:;Version=3;New=True;</property>
<property name=&quot;connection.release_mode&quot;>on_close</property>-->
<mapping assembly=&quot;Mapped.Assembly&quot; />
<mapping assembly=&quot;Mapped.Assembly2&quot; />

  </session-factory>
</hibernate-configuration>

Don’t forget to add all the assemblies in the mapping-assembly sections.
After that, the most interesting part is Burrow session initialization in order to add reference to the events. For example, this is what I have at the beginning of each test case that hits the database:

            var framework = new BurrowFramework();

            Configuration config = framework.BurrowEnvironment.GetNHConfig("PersistenceUnit1");

            // Poner los EventListeners
            config.SetListener(ListenerType.PostDelete, new FullTextIndexEventListener());
            config.SetListener(ListenerType.PostInsert, new FullTextIndexEventListener());
            config.SetListener(ListenerType.PostUpdate, new FullTextIndexEventListener());

            framework.BurrowEnvironment.RebuildSessionFactories();

The last line is important because it updates the session with the changes made. Ok, this may not be the best approach and adding the events in the nhibernate.cfg.xml would be better. It’s up to you. It should be something like this (the code goes into the session-factory section):

<listener class=&quot;NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search&quot; type=&quot;post-update&quot; />
<listener class=&quot;NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search&quot; type=&quot;post-insert&quot; />
<listener class=&quot;NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search&quot; type=&quot;post-delete&quot; />

With this code you don’t need to rebuild the session factory.
With this configuration, the indexable entities (see Dario Quintana’s post on NHibernate.Search) are managed automatically by the library without doing anything manually and in a transparent manner.
Finally, you only need to test the search over the indexes. In the simple test below, the code creates a NHibernate.Search session and makes a search over an indexed entity, following Dario’s example:

        [Test]
        public void SearchIndexedUser()
        {
            var session = Search.CreateFullTextSession(new BurrowFramework().GetSession());

            var qp = new QueryParser("UserName", new StopAnalyzer());
            var nhQuery = session.CreateFullTextQuery(qp.Parse("test"), typeof(User));

            var results = nhQuery.List();

            Assert.AreEqual(1, results.Count);
        }

You must take in account on important thing: NHibernate.Search uses the current transaction if there’s one and NHibernate.Burrow makes use of them, so if you want to persist the indexes before making the search, it’s not enough evicting the entity. You should do the following:

            new BurrowFramework().CloseWorkSpace();
            new BurrowFramework().InitWorkSpace();

With this piece of code we finish Burrow’s pending transaction and create a new one in order to persist all the index changes.
And this is all. With this samples you can integrate in a simple manner two interesting projects on top of NHibernate, that can be a bit tricky if you need to deal directly with the session and are using Burrow. As well, using the new event system introduced in the 2.0 branch of NHibernate avoids the use of interceptors that in many cases was painful.
Note that both projects were compiled from the trunk of nhcontrib against NHibernate 2.0.1GA.
I’ll be waiting for your comments.