How to include the Fluent NHibernate discriminator column in a composite key

Development No Comments

In our project, we’re sub classing multiple domain classes from a single Reference Data table – i.e. Volume and Weight types. Among other things, the reference data table contains discriminator, code and value columns. The ‘discriminator’ column stores the name of the class and is used by Fluent NHibernate to determine which subclass to instantiate, the ‘value’ column is the full name of the reference data item, and the ‘code’ column is the abbreviated version of the value.

The code and value together are unique, and a composite key is created containing them both.

We load in reference data from an excel spreadsheet, and at some point, there was a code and value pair added to a reference data type which matched exactly with a code and value pair from another reference data type. Attempting to add the second code value pair resulted in a unique key violation.

I needed to add the discriminator column into the composite key. If you’re using auto mapping, you’ll need to add an auto mapping override. Below is an example of creating a composite key containing the code, discriminator and value columns.

 public class ReferenceDataAutoMappingOverride : IAutoMappingOverride<ReferenceData>
 {
 public void Override(AutoMapping<ReferenceData> mapping)
 {
 const string uniqueKeyName = "UK_ReferenceData_discriminator_Code_Value";
 mapping.DiscriminateSubClassesOnColumn<string>("discriminator").UniqueKey(uniqueKeyName);
 mapping.Map(refData => refData.Code).UniqueKey(uniqueKeyName);
 mapping.Map(refData => refData.Value).UniqueKey(uniqueKeyName);
 }
 }

ASP.NET MVC – Multiple parameterised form submit buttons without Javascript

Development No Comments

The current project I’m working on involves a search page with multiple submit buttons in a single HTML form. Each submit button triggers a different behavior while posting all of the form data to the controller.

This method is compatible with both IE 6+ and Firefox. It also avoids the IE button bug where button values are not passed on HTTP POST.

After discussing a few design options we decided to allow the user to add the desired search parameters via selecting them one by one from a drop down list. The user will commonly want up to three parameters at a time and may want to remove parameters after adding.

The relevant basic requirements of the search page were as follows:

  • The form must work with JavaScript turned off
  • 26 optional parameters.
  • Display only the active parameters on screen.
  • The user must be able to add/remove parameters to/from the screen.
  • The user must be able to select individual items from the search results and download full XML certificate data for the selected records.
  • The user must be able to export all search results to a CSV file for processing in Excel.

Buttons on forms allow us to go through a single action on the controller, we’ll call this PerformAction.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult PerformAction(HomeModel model, ButtonActionModel buttonAction)
{
	model.Items.Where(x => x.Key == buttonAction.ActionValue);
	if (buttonAction.ActionName == ButtonActionNames.Remove.ToString())
	{
		RemoveItem(buttonAction.ActionValue, model);
	}
	TempModel = model;
	// Post-get-redirect pattern:
	// http://blog.jorritsalverda.nl/2010/03/10/maintainable-mvc-post-redirect-get-pattern/
	return RedirectToAction(ViewNames.Index, null);
}

PerformAction accepts two parameters; HomeModel contains all of the form data and ButtonActionModel contains the button parameter data.

public class ButtonActionModel
{
	public string ActionName { get; set; }
	public string ActionValue { get; set; }
}

The button model contains the name of the action (i.e. “Remove”) and the value of the action (i.e. “Parameter1″). The names and values are arbitrary and can be handled however you like in the PerformAction method.

In HTML, the buttons look like:

<input name="buttonaction:Remove:Parameter1" type="submit"
       value="Remove Parameter 1"></input>

We’ll need a custom model binder to create the ButtonAction model.

public class ButtonActionBinder : DefaultModelBinder
{
	public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
	{
		var request = controllerContext.HttpContext.Request;
		var formKeys = request.Form.AllKeys;
		ButtonActionModel result = null;
		var indexedbutton = formKeys.Where(x => x.StartsWith("buttonaction")).FirstOrDefault();
		if (indexedbutton != null)
		{
			result = new ButtonActionModel();
			var split = indexedbutton.Split(':');
			result.ActionName = split[1];
			if (split.Length > 2) result.ActionValue = split[2];
		}
		return result;
	}
}

The model binder above is fairly simple, searching the submitted form data for “buttonaction” which is the first part of the button name.

The binder then splits the button name based on the colons, using the second element as the ActionName and the third element as the ActionValue. Once this is done, the binding is complete and the bound model is returned.

Add the model binder to Application_Start in Global.asax.cs

ModelBinders.Binders.Add(typeof(ButtonActionModel),
                         new ButtonActionBinder());

Here’s an extended example demonstrating multiple parameterised form submit buttons without Javascript: MvcMultiSubmit

Bitbucket – wrong user on commit

Development No Comments

I was having an issue where after pushing my changes to bitbucket, the changesets listed a different user as having pushed the files.

For bitbucket, the commit username has to match your bitbucket username.

As commits in Mercurial are local, we have no way of controlling that you have set your username correctly. It is important for you to set this up in such a way that we can identify your user account on Bitbucket when you push your commits to us.

In tortoise-hg, the username setting is available through global settings->commit

Icons by N.Design Studio. Designed By Ben Swift, modified by Matt Button. Powered by WordPress, and Free WordPress Themes
Entries RSS Comments RSS Log in

Page optimized by WP Minify WordPress Plugin