Archive for category MVC

When your Boolean parameter says “oncheck” in JavaScript and what to do about it

In my MVC application, I was building a table using a partial view. One column was an HTML link whose onclick event was bound to the “show” method, and this method took two parameters, a string and a boolean:

 <table>
   <tr>
      <td><a onclick="show('@item.ID', '@item.IsVisible')">Click Me!</a></td>
   </td>
 </table>

Inside the “show” method, notice the “visible” checkbox. I am simply setting the “checked” property to true or false, depending on the value of the “visible” parameter:

function show(id, visible) {
 $("#id").val(id);
 $('#visible').prop('checked', visible);
}

When running this code, I got strange behavior, and using the Developer Tools (F12 in IE), I noticed that the string generating the edit button line looked like this:

 <td><a onclick="show('1', 'checked')">Click Me!</a></td>

Huh. How did that “checked” get in there? When I ran the debugger, and MVC code was correctly binding the Boolean variable to either “True” or “False”, so what’s with this “checked” things I’m seeing?

There were two problems here. First, I needed to modify the MVC code, calling the “ToString” method on the Boolean property:

    <td><a onclick="show('@item.ID', '@item.IsVisible.ToString()')">Click Me!</a></td>

Second, this would return “True” or “False”, with the first letter capitalized. JavaScript needs those values in lower case. So I set up a ternary operator to handle that:

function show(id, visible) {
  $('#visible').prop('checked', visible == "True" ? true : false);
}

Fixed!

Leave a comment

Converting a List of strings to a SelectList

I had a brief list of comma-separated strings that I was storing in the web.config file, and I needed to convert them into a SelectList to bind to a DropDownListFor control in MVC. For that, there was a very simple method:

TempData["FundingTypes"] = new SelectList(ConfigurationManager.AppSettings["CoasterTypes"]
     .Split(',').ToList());

If I had needed a List<SelectListItem> instead, I would have done this:

            TempData["FundingTypes"] = ConfigurationManager.AppSettings["CoasterTypes"]
                .Split(',')
                .Select(f => new SelectListItem() {
                    Text = f.ToString(),
                    Value = f.ToString()
                }).ToList();

Leave a comment

Showing MVC ModelState errors in the view

I wanted to show the various ModelState errors encountered in an MVC controller and display them in the view. So in my controller, I have a bit of code that loops through the errors and builds them in a string, adding an HTML line break between each error:

string errors = String.Empty;

foreach (ModelState modelState in ViewData.ModelState.Values) {
     foreach (ModelError error in modelState.Errors) {
          errors += “<br />” + error.ErrorMessage;
     }
}

ViewBag.Message = “The following errors have occurred: “ + errors;

In the view, I show my ViewBag variable. Notice that I use the Html.Raw method to display the HTML code properly in using Razor:

@Html.Raw(ViewBag.Message)

 

Leave a comment

HTML select value missing from MVC model after post

In my MVC project, I have a property that is either Y or N. No maybe, no empty string – “Y” or “N”.

public class Coaster {
     public string DoYouLikeCoasters { get; set; }
}

I first thought just to do a basic select element. Something simple:

<select id=”DoYouLikeCoasters”>
     <option value=”Y”>Y</option>
     <option value=”N”>N</option>
</select>

But when I checked the model in the controller after the form was posted, the “DoYouLikeCoasters” property was empty. I basically hadn’t told MVC that I wanted the property. In order to properly get the value to the controller, I needed to MVC-ify the select by using the Html.DropDownListFor. Since I just wanted “Y” and “N” as values, I still wanted to essentially hard-code the values. So here is how I did that:

@Html.DropDownListFor(model => model.DoYouLikeCoasters, new SelectListItem[] {
     new SelectListItem() { Value = “Y”, Text = “Y” },
     new SelectListItem() { Value = “N”, Text = “N” }
}, new { @class = “form-control”, @style = “width: 50px” })

Leave a comment

Defining a method in a view

I know there will be much gnashing of teeth from MVC purists for even thinking about designing a view this way, but if you need to define a method inside a view, you can do it like I show below. In this instance, I am writing a method that will take a date, determine if it is null, and return either the short date or an empty string:

First, the method, defined at the top of the view:

@{
 var getDate = new Func<DateTime, string>((date) => date != DateTime.MinValue ? date.ToShortDateString() : String.Empty);
}

And then calling the method:

@foreach (Models.Coaster item in Model.Coasters) {
 <p>@getDate(item.Date)</p>
}

Leave a comment

jQuery function to highlight drop down list not working

I had an HTML select control generated from MVC Razor:

@Html.DropDownList("coasters", (List<SelectListItem>)ViewBag.Coasters, "--Select--", new { @class = "form-control")

I had a jQuery method that was supposed to highlight the drop down list value using the “val” method:

function loadCoaster(coaster) {
        $('#coasters').val(coaster);
}

But it wasn’t working. The value in the drop down list would flash briefly, then disappear.

What I found worked was setting the “selected” attribute by using jQuery’s “attr” method:

function loadCoaster(coaster) {
        $('select[name^="coasters"] option[value="' + coaster + '"]').attr("selected", "selected");
}

Using this, the value stuck.

Leave a comment

Partial View returning the full view instead of partial view contents

I had an odd result trying to return an ASP.NET MVC partial view from a controller after a POST request. The setup was simple.  I had a view that contained a partial view with a grid. Nothing fancy in the view:

@model IEnumerable<Models.Code>

<h2>Code Maintenance</h2>

@{     Html.RenderPartial("~/Views/_CodeTable.cshtml", Model); }

The partial view contained a table:

@model IEnumerable<Models.Code>

<table class="table table-striped table-bordered">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Code)
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Code)
            </td>
            <td><a onclick="loadCode(this, '@item.Code')"></a></td>
        </tr>
    }
</table>

When the page loaded initially, everything was fine. But when I tried to update the partial view using some jQuery code, the I would get HTML results like so:

<h2>Code Maintenance</h2>

<h2>Code Maintenance</h2>

<table>
 <tr><td>1</td></tr>
 <tr><td>2</td></tr>
 <tr><td>3</td></tr>
</table>

There was also global code in the _layout.cshtml being returned as part of the partial view, though I am not showing that here. So basically, the partial view wasn’t being treated like a partial view, and was instead being treated like a view, and the “Code Maintenance” title, along with my _layout.cshtml code, was being displayed twice when it should have only been shown once.

The problem in this case was my controller. I was returning a view instead of a partial view. Here is wrong code:

        [HttpPost]
        public ActionResult Code(Code model) {
            List<Code> results = new List<Code>();
            ...
            return View(results);
        }

And here is the corrected code:

     [HttpPost]
     public ActionResult Code(Code model) {
         List<Code> results = new List<Code>();
         ...
         return PartialView("_table", results);
     }

In case you are curious, here is how I loaded the code in jQuery:

function updateCode(id) {

    var data = { id: id };

    $.ajax({
        url: uri + 'MyController/UpdateCode',
        type: 'POST',
        cache: false,
        async: false,
        contentType: 'application/json',
        data: JSON.stringify(data),
        success: function (partialViewResult) {
            $("#results").html(partialViewResult);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            alert('Error saving the code');
        }
    });
}

Leave a comment