Blog Stats
  • Posts - 52
  • Articles - 0
  • Comments - 6
  • Trackbacks - 0

 

Wednesday, May 08, 2013

Semantic Versioning


In a discussion about software product versioning, the post on Semantic Versioning came up. I found the essay to reflect commonly recognized best practices. However, the value of the essay is in the concise and rigorous rules for incrementing version numbers. 

Monday, March 11, 2013

Retain and Set Posted Checkbox Value in the MVC 4 Controller


I believe this is a bug where only the checkbox value is not retained when passing the model from the view to a post method.

Model

public bool CoreField { get; set; }

View

@model List<Model>

@Html.CheckBoxFor(m => m[i].CoreField, 
 new { @id = "cbCoreField" + i })@Html.HiddenFor(m => m[i].CoreField)
@Html.Hidden("fIsCore", 
 null, new { @id = "hIsCore" + i }) 
//has to use separate list instead of model due to MVC bug

Note the use of “fIsCore” as a separate list used to pass changes to the checkbox into the post method and the use of ModelState.SetModelValue to set the checkbox value for redisplay when the model is invalid (i.e. adding a row where the model validation rules for some other field has been violated.

Controller Post Method

[HttpPost]
        public ActionResult Index(List<Model> model, List<bool> fIsCore)
        {
            if (!(model == null))
            {
                if (ModelState.IsValid)
                {
                    int i = 0;
                    foreach (var item in model)
                    {
                        item.CoreField = fIsCore[i];
                        i++;

                        if (!(item.ID == 0))
                        {
                            db.Entry(item).State = EntityState.Modified;
                        }
                        else
                        {
                            db.Model.Add(item);
                        }
                    }
                    db.SaveChanges();
                }
                else
                {
                    //ModelState.Clear(); // not needed now
                    int i = 0;
                    foreach (var item in model)
                    {
                        string key = string.Format("[{0}].CoreField", i);
                        item.CoreField = fIsCore[i];
                        ModelState.SetModelValue(key, 
                            new ValueProviderResult(item.CoreField, 
                                "",
                                CultureInfo.InvariantCulture));
                        i++;
                    }

                    return View(model);
                }
            }
            return RedirectToAction("Index");
        }

Tuesday, March 05, 2013

Using the DIR command in the TFS 2010/12 Team Build Invoke Process Activity


I found that using a loop activity to build up a filtered list clutters up the build report with repetitions of activities inside the loop. I could write a custom activity to create the list. However, rather than have to write and maintain code, it’s possible to use the DOS DIR command in the Invoke Process activity.

First, because there is no dir.exe file, you must execute a windows shell. I used “cmd” as the FileName value. 

image

Then in the Arguments value I use the shell /c switch followed by the DIR  command. It’s also possible to exclude file types from the list.

String.Format("{0} ""{1}"" {2}",  "/c dir",  BinariesDirectory,  "/b  |findstr /vi "".zip""")

Thursday, January 24, 2013

Setting HTML.CheckBoxFor Values in MVC 4 View from Json return using jQuery Ajax Script


I’m an MVC/jQuery noobie and this one really got my goat for while. The problem was handling the bit field in SQL Server which was treated as a checkbox field in MVC.

Here’s how you can set a checkbox value based the the user’s selection from dropdown list on the same view:

Model:

public string Field_Ref_Name { get; set; } // the dropdown list 
public bool CoreField { get; set; } // the checkbox

Controller:

From the Get ActionResult method to populate the dropdown list.  
ViewBag.projectConditionWitRefFieldsDropdownList = 
                new SelectList(refFieldList, selectedField);

The JsonResult method called by the jQuery script in the view.

public JsonResult GetFieldAttributes(string selectedField)
        {
            string a = selectedField;
            bool b = false;
            if (!(selectedField.Contains("some value")))
            {
                b = true;
            }
            
            var dataParms = new { aA = a, aB = b };
            return Json(dataParms, JsonRequestBehavior.AllowGet);
        }

View:

The script, which gets the bool from the Json result and sets the checkbox. Note I had to use the “click” event to set the checkbox. All efforts to use some sort of checked true or false approach failed. The trick is the conditional logic of the data.aB boolean return value.

<script type="text/javascript">
     $(function() {
            $("#ddlField").change(function() {
                var selectedItem = $(this).val();
                $.ajax({
                    cache: false,
                    type: "GET",
                    url: "@(Url.Action("GetFieldAttributes", "ConditionDetails"))",
                    data: { "selectedField": selectedItem},
                    success: function (data) {
                        $("#DataType").val(data.aA);
                        if (data.aB) {
                            var chk = $('#CoreField').is(':checked');
                            if (!(chk)) {
                                $("#CoreField").click();
                            }
                        }
                        else {
                            var chk = $('#CoreField').is(':checked');
                            if (chk) {
                                $("#CoreField").click();
                            }
                        }
                    },
                    error:function (xhr, ajaxOptions, thrownError){
                        alert('Failed to return core and type field attributes.');

                    }  
                });
            });
        });
    </script>

From the razor code to display the page.

@using (Html.BeginForm()) 
        {
            @Html.ValidationSummary(true)

            <fieldset>
                <legend>Condition_Details</legend>

                <div class="editor-label">
                    @Html.LabelFor(model => model.Field_Ref_Name)
                </div>
                <div class="editor-field">
                    @if (@ViewBag.projectFilterSelected)
                    {
                        @Html.DropDownListFor(model => model.Field_Ref_Name, 
                        ViewBag.projectConditionWitRefFieldsDropdownList as SelectList, 
                            string.Empty, new { @id = "ddlField", style = "font-size: .85em; font-weight: normal;" })
                    }
                    else
                    {
                        @Html.EditorFor(model => model.Field_Ref_Name)
                    } 
                    @Html.ValidationMessageFor(model => model.Field_Ref_Name)
                </div>

                <div class="editor-label">
                    @Html.LabelFor(model => model.DataType)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.DataType)
                    @Html.ValidationMessageFor(model => model.DataType)
                </div>

                <div class="editor-label">
                    @Html.LabelFor(model => model.CoreField)
                </div>
                <div class="editor-field">
                    @Html.CheckBoxFor(model => model.CoreField)
                    @Html.ValidationMessageFor(model => model.CoreField)
                </div>

            </fieldset>
        }

Wednesday, January 02, 2013

MVC ModelState.IsValid Fails When Reserved Word Used for Table Name


When a table name uses a reserved word: for example, “Action,” model validation will fail even though the model is valid. The error message from ModelState is:

“The parameter conversion from type 'System.String' to… …type failed because no type converter can convert between these types.”

For example, if a table named Action has a related table, Action_Details, where an Action may have one to many Action_Conditions, you may have a model class for Action_Details that looks like this:

    public class Action_Details
    {
        public int ID { get; set; }
        public int Action_ID { get; set; }
        public string Value { get; set; }
        public string ParentField { get; set; }
        public string ChildField { get; set; }
        public Nullable<bool> Inherit { get; set; }
        public virtual Action Action { get; set; } 
    }

My solution was to change the related table class

    public class Action_Details
    {
        public int ID { get; set; }
        public int Action_ID { get; set; }
        public string Value { get; set; }
        public string ParentField { get; set; }
        public string ChildField { get; set; }
        public Nullable<bool> Inherit { get; set; }
        //public virtual Action Action { get; set; } 
        // ** as "Action" is a reserved word, I had to use the 
        // ** fully qualified class name (i.e. UI.Models.Action) 
        // ** AND change the object name from Action to Action1
        public virtual UI.Models.Action Action1 { get; set; }
    }

Thursday, December 27, 2012

LINQ (C#) Many to Many Query using Entity Framework


Using a MVC 4 Code First project I noticed that my intermediate table between a many to many relationship was missing. In other words, Table 1 has many Table 3, and Table 3 has many Table 1. In the database schema, Table 2 is my intermediate table:

  • Table 1 has many Table 2 and Table 2 has only one Table1
  • Table 3 has many Table 2 and Table 2 has only one Table3, as follows:

 

 EF

However, as I stated earlier, I did not have a model class for Table 2.  At first I was miffed, but once I was able to craft the query, I was impressed at how easy EF made this.  I wanted to get a listing of Table 3 fields for a specific ProjectID (pID) in Table 1.  Here’s the query :)

var Table3Qry = from t3 in db.Table3 
from t2 in t3.Table1.Where(x => x.ProjectID == pID) 
select new { t3.foo1, t3.foo2, t3.foo3 };

Friday, December 21, 2012

ASP.NET MVC 4 - My FAQs


Here are some FAQs on things that were not so obvious. I’ll continue to add to this list over time.

1. Passing HtmlAttributes using @Html.ActionLink

@Html.ActionLink("Create New", "Create", null, 
new { style="font-size: .75em; font-weight: normal; padding-left: 15px;" })

2. Html.EditFor with multiline and word wrap support

Use the following data annotation in the model class:
[DataType(DataType.MultilineText)]
public string TextField { get; set; }
This requies the following using statement in the model class:
using System.ComponentModel.DataAnnotations;
Multi-line and word wrap is rendered in the view without any further changes in the controller and view.

3. Pass a variable when using return RedirectToAction

return RedirectToAction("Index", null, new { foo = "some value" });

4. Insert a row and link

This was a frustrating problem that took me some time to resolve. However, the solution is very simple.

See this posting on the ASP.NET MVC forum.

5. Attach existing many-to-many entities using LINQ in the post method

I couldn’t quickly find a simple guide to help me with these basic operations. 
It took me a while to work out the solution.
public ActionResult Attach(List<Class> classList, int studentID, string command)
        {
            if (ModelState.IsValid)
            {
                int l = command.IndexOf(" ");
                int clickedClassID = Int32.Parse(command.Substring(0, l));
                var condition = db.Conditions.Find(conditionID);

                foreach (var class in classList)
                {
                    if (class.ID == clickedClassID )
                        if (command.Contains("Attach"))
                        {
                            //not sure why I needed to declare the following 2 variables, 
			//but otherwise it didn't work

		var existingClass = db.Classes.SingleOrDefault(x => x.ID == class.ID);
                  var existingStudent = db.Students.First(x => x.ID == studentID);

                            existingClass.Students.Add(existingStudent);
                            db.Classes.Attach(existingClass);

                            db.Entry(existingClass).State = EntityState.Modified;
                            db.Entry(existingStudent).State = EntityState.Modified;
                            db.SaveChanges();
                        }
                else
                }
            }
            return View(db.Classes.ToList());
        }

6. Creating local variables in the view from the ViewBag for use in JQuery

<script>
  var someStringValue = '@(ViewBag.someStringValue)';
  var someNumericValue = @(ViewBag.someNumericValue);
</script>

7. Add a New Row to an Editable Index View

see Stackoverflow at:

http://stackoverflow.com/questions/15249466/mvc-4-partialviewresult-return-partialview-calls-wrong-view-url

Tuesday, December 18, 2012

MVC4 Razor @Html.DropDownList with Entity Framework Code First


Controller

ViewData["Projects"] = new SelectList(db.Projects.Select(r => r.ProjectName));
View
@Html.DropDownList("Projects")

There were many complicated examples, but this worked for me. However, I needed to pull from a database and manipulate the data before populating the dropdown. Here’s what I ended up with:

Controller

//retrieve the list of projects from the projects table
var ProjectQry = (from p in db.Projects orderby p.Project_Name
             select new { projectName = p.Project_Name, ID = p.ID }).ToList();

//format project name and ID into single field
var projectList = from p in ProjectQry 
             select new { project = p.projectName + " (" + p.ID + ")" };
            

//send the list and return
ViewData["selection"] = new SelectList(dropdownList.Select(i => i.project), blankLine);
return View();
View

//formats and inserts a blank line as the default in the list @Html.DropDownList(

"selection", null, string.Empty,

new { style = "font-size: .85em; font-weight: normal;" })

Friday, December 14, 2012

Entity Framework for Visual Studio 2012 Update 1: Reverse Engineer Bug and System.Data.Entity.Infrastructure


I had a couple of minor delays setting up Entity Framework in Visual Studio 2012 Update 1.

  1. Reverse engineering the database failed with the following error: “A processor named 'T4VSHost' could not be found for the directive named 'CleanupBehavior'. The transformation will not be run.”

The work around for C# projects is to:

Open the File
C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\Templates\Includes\EF.Utility.CS.ttinclude (for C#)

And Remove the First Line:
<#@ CleanupBehavior Processor="T4VSHost" CleanupAfterProcessingTemplate="true" #>

See this bug in Connect  for more details.

     2.  Finding the reference for “using System.Data.Entity.Infrastructure.”  The procedure to add this reference is:

In Visual Studio 2012, select menu item "Tools"-> Library Package Manager -->  Package Manger Console 
and typing there:
PM> install-package EntityFramework

See this forum post for more details.

Simple TFS 2012 API Methods: List Projects in a Collection and Import WIT Definitions


I found a lot of code to do these things, but really appreciated a more concise and simple approach. For example, this can be run as a unit test.

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Xml;
using System.Collections.Generic;
using System.Linq;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
[TestMethod]
        public void ImportProcessTemplateWitDefinitionsToCollection()
        {
            string wsPath = @"{your path}\WorkItem Tracking\TypeDefinitions\";
            List<string> wits = new List<string>();
            wits.Add("Bug.xml");
            wits.Add("Task.xml");
            wits.Add("UserStory.xml");

            TfsTeamProjectCollection tpc = 
                new TfsTeamProjectCollection(new Uri("{your collection url}"))
            tpc.EnsureAuthenticated();
            var wis = new WorkItemStore(tpc);
            var projects = (from Project p in wis.Projects select p.Name).ToList();

            foreach (var targetTfsProjectName in projects)
            {
                foreach (string wit in wits)
                {
                    XmlDocument WitDefFile = new XmlDocument();
                    WitDefFile.Load(wsPath + wit);
                    string WitDef = WitDefFile.InnerXml;
                    wis.Projects[targetTfsProjectName].WorkItemTypes.Import(WitDef);
                }
            }
        }
 

 

Copyright © Bob Hardister