Wednesday, February 24, 2016

Castle.MicroKernel.Registration.AllTypes' is obsolete in ASP.NET MVC 5

In the event that you'll be referencing Castle Windsor 3.3.0 and incorporate the IOC container in your project, you will encounter the error stated by the title of this post. This happens when you use register the controllers to the IOC container using AllTypes class.

1
2
3
4
container.Register(AllTypes.FromThisAssembly()
      .Pick().If(t => t.Name.EndsWith("Controller"))
      .Configure(configurer => configurer.Named(configurer.Implementation.Name))
      .LifestylePerWebRequest());

This class has been deprecated in the recent versions of Castle Windsor. The solution is to update the Register method and replace AllTypes with Castle.MicroKernel.Registration.Classes.

1
2
3
4
container.Register(Classes.FromThisAssembly()
     .Pick().If(t=> t.Name.EndsWith("Controller"))
     .Configure(configurer => configurer.Named(configurer.Implementation.Name))
     .LifestylePerWebRequest());

Friday, February 19, 2016

Read JSON Array using Json.NET JsonTextReader

Given the sample JSON data below, you might wanna parse the information provided and retrieve the name property of a JSON Array StartObject and add it to a list box control.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
[
  {
    "_id": "56c762b9d508f4622b732a4b",
    "index": 0,
    "guid": "72e418b1-c54b-4695-9f43-add4b2455bf2",
    "isActive": false,
    "balance": "$1,998.49",
    "picture": "http://placehold.it/32x32",
    "age": 32,
    "eyeColor": "green",
    "name": "Jodie Larson",
    "gender": "female",
    "company": "MENBRAIN",
    "email": "jodielarson@menbrain.com",
    "phone": "+1 (957) 432-3322",
    "address": "138 Bainbridge Street, Singer, North Dakota, 455",
    "about": "Quis sint tempor ut nostrud cupidatat proident duis cupidatat sit in commodo. Ipsum minim magna qui eiusmod qui duis. Do commodo eiusmod consectetur magna. Ea do eu cillum nostrud in consequat do nulla minim nisi quis esse tempor. Voluptate laborum fugiat incididunt adipisicing. Culpa laboris cillum proident irure ea esse nostrud laborum tempor exercitation nisi do et sit.\r\n",
    "registered": "2014-10-13T08:18:08 -08:00",
    "latitude": -74.060005,
    "longitude": 105.314647,
    "tags": [
      "ad",
      "laborum",
      "ad",
      "sint",
      "tempor",
      "sit",
      "irure"
    ],
    "friends": [
      {
        "id": 0,
        "name": "Barton Reynolds"
      },
      {
        "id": 1,
        "name": "Potter Hess"
      },
      {
        "id": 2,
        "name": "Keisha Benton"
      }
    ],
    "greeting": "Hello, Jodie Larson! You have 7 unread messages.",
    "favoriteFruit": "apple"
  },
  {
    "_id": "56c762b916285e8fd29eb44c",
    "index": 1,
    "guid": "02e7eb08-784f-43b4-bd1d-f850ebc1426a",
    "isActive": false,
    "balance": "$3,944.92",
    "picture": "http://placehold.it/32x32",
    "age": 37,
    "eyeColor": "brown",
    "name": "Gay Vega",
    "gender": "male",
    "company": "EBIDCO",
    "email": "gayvega@ebidco.com",
    "phone": "+1 (889) 480-3836",
    "address": "769 Rewe Street, Loomis, District Of Columbia, 1897",
    "about": "Aute commodo exercitation sint amet consectetur est fugiat ipsum. Aliquip laboris incididunt veniam aliquip enim tempor sint deserunt nulla. Anim qui ex laborum est aliquip. Anim dolor nostrud officia voluptate reprehenderit nostrud pariatur incididunt adipisicing mollit aliqua aute sunt. Deserunt reprehenderit eiusmod nisi aliqua in consequat est id sunt sit amet. Do magna culpa laboris reprehenderit adipisicing. Irure consectetur sunt duis tempor aute nostrud aute amet veniam veniam dolore in Lorem ipsum.\r\n",
    "registered": "2014-06-11T10:18:40 -08:00",
    "latitude": 70.157205,
    "longitude": -121.311015,
    "tags": [
      "laboris",
      "quis",
      "nulla",
      "cupidatat",
      "ea",
      "anim",
      "adipisicing"
    ],
    "friends": [
      {
        "id": 0,
        "name": "Craig Barrett"
      },
      {
        "id": 1,
        "name": "Blackburn Callahan"
      },
      {
        "id": 2,
        "name": "Harmon Herring"
      }
    ],
    "greeting": "Hello, Gay Vega! You have 10 unread messages.",
    "favoriteFruit": "apple"
  },
  {
    "_id": "56c762b913e08057a4385445",
    "index": 2,
    "guid": "2c6cd943-c7b9-4ce2-8e05-90c97f12fbca",
    "isActive": false,
    "balance": "$2,246.38",
    "picture": "http://placehold.it/32x32",
    "age": 30,
    "eyeColor": "brown",
    "name": "Joseph Snow",
    "gender": "male",
    "company": "XSPORTS",
    "email": "josephsnow@xsports.com",
    "phone": "+1 (900) 488-3291",
    "address": "303 Fillmore Avenue, Gardiner, North Carolina, 2107",
    "about": "Nulla ad aute mollit culpa excepteur consectetur eiusmod. Lorem et voluptate exercitation nulla occaecat deserunt ipsum ex officia Lorem id elit commodo. Commodo nulla minim minim mollit aliqua ex ex anim sint ex pariatur sunt. Aute non sint elit ullamco labore. Velit aliqua nulla qui dolor veniam est. Velit Lorem adipisicing sunt aliquip pariatur eu commodo. Esse duis proident non magna labore cillum reprehenderit velit velit laboris aliqua commodo.\r\n",
    "registered": "2014-07-04T12:06:36 -08:00",
    "latitude": 25.464785,
    "longitude": 174.230961,
    "tags": [
      "ut",
      "qui",
      "esse",
      "aute",
      "esse",
      "enim",
      "nisi"
    ],
    "friends": [
      {
        "id": 0,
        "name": "Mills Delaney"
      },
      {
        "id": 1,
        "name": "Caroline Bonner"
      },
      {
        "id": 2,
        "name": "Sarah Wilder"
      }
    ],
    "greeting": "Hello, Joseph Snow! You have 1 unread messages.",
    "favoriteFruit": "strawberry"
  },
  {
    "_id": "56c762b912271dea945f2e74",
    "index": 3,
    "guid": "05d5b0c0-1202-4208-8590-519057212999",
    "isActive": false,
    "balance": "$2,740.09",
    "picture": "http://placehold.it/32x32",
    "age": 21,
    "eyeColor": "blue",
    "name": "Brenda Nash",
    "gender": "female",
    "company": "COMSTRUCT",
    "email": "brendanash@comstruct.com",
    "phone": "+1 (999) 579-2688",
    "address": "945 Adler Place, Hiseville, Massachusetts, 3011",
    "about": "Exercitation laboris tempor Lorem exercitation occaecat id aliquip sit duis. Exercitation magna mollit est exercitation mollit excepteur ullamco. Ipsum Lorem magna occaecat esse. Laborum cupidatat ipsum labore Lorem sunt magna ex exercitation est duis ullamco mollit minim pariatur. Sit occaecat in laborum est mollit in aute proident ex officia adipisicing. Eu cupidatat veniam non do.\r\n",
    "registered": "2016-02-17T01:38:18 -08:00",
    "latitude": -4.068155,
    "longitude": -38.59591,
    "tags": [
      "occaecat",
      "non",
      "excepteur",
      "nisi",
      "nulla",
      "laboris",
      "consectetur"
    ],
    "friends": [
      {
        "id": 0,
        "name": "Hogan Wyatt"
      },
      {
        "id": 1,
        "name": "Gale Finch"
      },
      {
        "id": 2,
        "name": "Estela Dale"
      }
    ],
    "greeting": "Hello, Brenda Nash! You have 8 unread messages.",
    "favoriteFruit": "strawberry"
  },
  {
    "_id": "56c762b90e4c1f80956b1c25",
    "index": 4,
    "guid": "5edebad7-fdc7-42da-8704-2ac93afffb2a",
    "isActive": true,
    "balance": "$3,311.82",
    "picture": "http://placehold.it/32x32",
    "age": 31,
    "eyeColor": "blue",
    "name": "Herring Cooper",
    "gender": "male",
    "company": "PYRAMIS",
    "email": "herringcooper@pyramis.com",
    "phone": "+1 (830) 571-3393",
    "address": "131 Vanderbilt Street, Iola, Wisconsin, 5269",
    "about": "Labore officia eiusmod occaecat aliquip proident laboris enim enim reprehenderit sint cupidatat ex consequat deserunt. Sint proident laborum labore ex et nulla non eiusmod incididunt voluptate fugiat incididunt sint. Adipisicing nisi consequat incididunt nulla laborum fugiat do in excepteur aliqua. Labore minim eiusmod dolor duis. Ad elit eiusmod ex sit qui ad velit. Tempor elit mollit magna labore nisi quis deserunt cupidatat fugiat cupidatat.\r\n",
    "registered": "2014-10-15T12:04:06 -08:00",
    "latitude": 59.087757,
    "longitude": -85.817126,
    "tags": [
      "id",
      "magna",
      "velit",
      "minim",
      "proident",
      "incididunt",
      "qui"
    ],
    "friends": [
      {
        "id": 0,
        "name": "Marilyn Schroeder"
      },
      {
        "id": 1,
        "name": "Bobbie Osborne"
      },
      {
        "id": 2,
        "name": "Eunice Ortega"
      }
    ],
    "greeting": "Hello, Herring Cooper! You have 2 unread messages.",
    "favoriteFruit": "strawberry"
  },
  {
    "_id": "56c762b9fd970fe73b8e9208",
    "index": 5,
    "guid": "42d19967-5daf-4fa4-97aa-140fd95be7dd",
    "isActive": false,
    "balance": "$2,400.40",
    "picture": "http://placehold.it/32x32",
    "age": 26,
    "eyeColor": "green",
    "name": "Kirby Barker",
    "gender": "male",
    "company": "BISBA",
    "email": "kirbybarker@bisba.com",
    "phone": "+1 (958) 568-3754",
    "address": "467 Argyle Road, Matthews, Delaware, 114",
    "about": "Ullamco labore ea anim quis nisi ut reprehenderit aliquip. Aute excepteur pariatur qui voluptate esse pariatur. Adipisicing cupidatat ipsum ea id amet exercitation labore veniam. Ex magna aliquip nostrud eiusmod proident incididunt tempor quis officia et cillum qui esse. Velit non dolor esse proident. Qui sunt magna elit Lorem proident esse dolor duis. Est nostrud qui incididunt occaecat laborum et ad eu esse sint.\r\n",
    "registered": "2014-12-21T04:48:16 -08:00",
    "latitude": 37.53505,
    "longitude": -132.579884,
    "tags": [
      "deserunt",
      "sint",
      "ipsum",
      "exercitation",
      "commodo",
      "ut",
      "consectetur"
    ],
    "friends": [
      {
        "id": 0,
        "name": "Kelley Hensley"
      },
      {
        "id": 1,
        "name": "Long Gentry"
      },
      {
        "id": 2,
        "name": "Mari Mcneil"
      }
    ],
    "greeting": "Hello, Kirby Barker! You have 7 unread messages.",
    "favoriteFruit": "strawberry"
  },
  {
    "_id": "56c762b91b039520117ffe1c",
    "index": 6,
    "guid": "1388e4e0-d6d9-40d5-80b7-d582f5a8765c",
    "isActive": true,
    "balance": "$3,883.07",
    "picture": "http://placehold.it/32x32",
    "age": 22,
    "eyeColor": "blue",
    "name": "Calderon Wolf",
    "gender": "male",
    "company": "IDEGO",
    "email": "calderonwolf@idego.com",
    "phone": "+1 (824) 596-2676",
    "address": "420 Huron Street, Farmers, Oklahoma, 9496",
    "about": "Ullamco non occaecat Lorem quis sunt officia pariatur exercitation. Tempor sit occaecat est mollit proident officia nostrud dolore qui veniam dolore occaecat magna. Incididunt non officia consectetur cupidatat eu ad amet nulla. Labore id ad aliqua reprehenderit culpa deserunt enim. Occaecat laboris pariatur est laboris nisi amet anim.\r\n",
    "registered": "2015-08-16T04:40:28 -08:00",
    "latitude": 64.331478,
    "longitude": -1.070689,
    "tags": [
      "dolor",
      "ad",
      "commodo",
      "eiusmod",
      "id",
      "dolor",
      "ea"
    ],
    "friends": [
      {
        "id": 0,
        "name": "Hallie Sexton"
      },
      {
        "id": 1,
        "name": "Maryellen Roberts"
      },
      {
        "id": 2,
        "name": "Palmer Beard"
      }
    ],
    "greeting": "Hello, Calderon Wolf! You have 5 unread messages.",
    "favoriteFruit": "apple"
  }
]

In order to achieve the desired output similar to this screenshot.

A solution is to parse the JSON data using the JsonTextReader class.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
void SolutionJsonTextReader()
{
    int count = 0;
    WebClient itemListDataWC = new WebClient();
    var responseData = itemListDataWC.DownloadString("datasample.json");
 
    JsonTextReader reader = new JsonTextReader(new StringReader(responseData));
    while (reader.Read())
    {
        if (reader.TokenType == JsonToken.StartObject)
        {
            JObject obj = JObject.Load(reader);
            lstName.Items.Add(obj["name"]); //load names to listbox
        }
        else
        {
            continue;
        }
    }
}
The preceding code, assigns the responseData object to a StringReader constructor and then assigned in the JsonTextReader constructor class. Inside the loop statement, the code checks if the reader is of type StartObject. If true, load the reader to a JSON object. In turn, we can obtain the name property of that object.

Tuesday, February 16, 2016

ASP.NET MVC 5 Client Side Form Validation using jQuery and Bootstrap

Hello,

Here's a VB.NET example on how to perform form validation using jQuery and Bootstrap without Model class. Validation is performed purely on the client side. The steps are explained in detail at VBForums codebank ASP.NET MVC 5 Form Validation using jQuery and Bootstrap without Model class and the source code can be downloaded in github MVCFormValidationJQueryValidateVB.
Screenshots:


That's it.. :-)

Saturday, February 13, 2016

ASP.NET MVC 5 jQuery validation form.validate() method in external JavaScript file not firing

I have an external JavaScript file that validates a form using form.validate() of jQuery validation plugin.
$(function () {
    
    $("#frmInput").validate({
        submitHandler: function (form) {
            //submit once validation rules are met
            form.submit();           
        },
        .....other codes here
    });
});

When integrating it in an MVC 5 application, the validate event does not trigger. I have checked if there are errors using the Chrome developer tools and Firefox but to no avail there is none. The solution I discovered was to change the BundleConfig.cs file and the order of scripts rendering in _Layout.cshtml. After that, form validation now works.

Steps:
1. Change BundleConfig.cs codes
//change code in BundleConfig.cs From:
 
bundles.Add(new ScriptBundle("~/bundles/jqueryval")
.Include("~/Scripts/jquery.validate*"));
 
//To: (individual bundling of validate and unobtrusive js files)
 
bundles.Add(new ScriptBundle("~/bundles/jqueryval")
.Include("~/Scripts/jquery.validate.min.js"));
 
bundles.Add(new ScriptBundle("~/bundles/jqueryunobtrusive")
.Include("~/Scripts/jquery.validate.unobtrusive.min.js"));

2. Change rendering of scripts code in _Layout.cshtml
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/jquery")   
@Scripts.Render("~/bundles/bootstrap")
@Scripts.Render("~/bundles/jqueryval")
@Scripts.Render("~/bundles/RegistrationFormValidation") @* validate form *@
@Scripts.Render("~/bundles/jqueryunobtrusive") 
@Scripts.Render("~/bundles/modernizr") 

Note: There may be other solutions as to why form.validate() does not work. This is just a workaround.

Friday, February 12, 2016

Large spacing between form controls in ASP.NET MVC 5 (VB.NET) project

As I was converting a registration form from MVC 5 C# website to VB.NET MVC 5, I've noticed that in VB.NET the div elements with form-group class have different spacing in between compared with the former project. I've doubled checked and compared Site.css and my custom css files and all styles are the same.

Luckily, I found out that MVC 5 VB.NET project includes the older version of Bootstrap that is version 3.0. So, replacing the old bootstrap files in VB.NET project with bootstrap.min.css and bootstrap.css version 3.3.6 corrected the issue.

Thursday, February 11, 2016

ASP.NET MVC 5 Client-Side Remote Validation using jQuery

When integrating jQuery validation in ASP.NET MVC, here's how to apply client-side remote validation using javascript code. Below are the snippets and screenshots. Make sure to render the jquery.validate.min.js file in your View or Layout.

Email HTML Markup:
1
2
3
4
5
6
7
<div class="form-group has-feedback">
  <label for="email" class="control-label col-md-3">Email Address:</label>
  <div class="col-md-9">
      <input type="email" name="email" id="email" class="form-control" placeholder="Enter email" />
     <span class="glyphicon form-control-feedback" id="email1"></span>
  </div>
</div>

Custom Javascript Validation Code:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$(function () {    
    $("#frmInput").validate({
        submitHandler: function (form) {
            //submit once validation rules are met
            form.submit();           
        },
        rules: {
            .... //other validation statements
 
            email: {
                required: true,
                email: true,
                remote: {
                    url: "/Home/EmailExists",
                    type: "post",
                    data: {
                        email: function () {
                            return $('#email').val();
                        }
                    }
                }
            }            
        },
        messages: {
            email: {
                remote: "Email already in use!"
            }
        }
           .... //other validation statements
    });
});

Controller Method (You may replace the statements with database checking):
1
2
3
4
5
[HttpPost]
public JsonResult EmailExists(string email)
{
     return Json(!String.Equals(email, "gregmail@co.uk", StringComparison.OrdinalIgnoreCase));
} 

Invalid Email (Existing/Used):
Valid Email(New/Unused):

Wednesday, February 10, 2016

ASP.NET MVC WebGrid in Partial View redirects to blank page during pagination

I've created an ASP.NET MVC website that loads a partial view with a WebGrid control on ajax call. When I tested navigating to next record set, the WebGrid performs a postback and then redirects to a blank page. Not only that, the WebGrid control also lost it's css style.
After doing some research on it's properties, I basically encountered a property called ajaxUpdateContainerId. After including that property in the WebGrid control, the pagination works fine and does not redirect to a blank page.
Original Code:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@{
    var grid = new WebGrid(
        canPage: true, 
        canSort: true, 
        rowsPerPage: 10);
    grid.Bind(Model.AddressList, rowCount: Model.AddressList.ToList().Count);
    grid.Pager(WebGridPagerModes.NextPrevious);
    @grid.GetHtml(tableStyle: "webGrid",
                            htmlAttributes: new { id = "grid" },
                            headerStyle: "header",
                            alternatingRowStyle: "alt",
                            columns: grid.Columns(
                                        grid.Column("AddressLine1", "Address Line", canSort: true),
                                        grid.Column("City", "City", canSort: true),
                                        grid.Column("PostalCode", "Postal Code", canSort: true)
                            ));
}

Screenshot:

Updated Code:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@{
    var grid = new WebGrid(
        canPage: true,
        rowsPerPage: 10,
        canSort: true,
        ajaxUpdateContainerId: "grid"
    );
    
    grid.Bind(Model.AddressList, rowCount: Model.AddressList.ToList().Count);
    grid.Pager(WebGridPagerModes.All);
}
 
@grid.GetHtml(
    htmlAttributes: new { id = "grid" },
    tableStyle: "webGrid",
    headerStyle: "header",
    alternatingRowStyle: "alt", 
    columns: grid.Columns(
             grid.Column("AddressLine1", "Address Line", canSort: true),
             grid.Column("City", "City", canSort: true),
             grid.Column("PostalCode", "Postal Code", canSort: true)
    )
)

Screenshot:

LINQ to SQL In Operator with Subquery

Given the following sql statement below using In operator with subquery as it's argument, I need to convert this to LINQ statement.
SELECT [CountryRegionCode]
      ,[Name]
      ,[ModifiedDate]
  FROM [AdventureWorks2012].[Person].[CountryRegion]
  where CountryRegionCode in (select distinct [CountryRegionCode] 
  from [AdventureWorks2012].[Person].StateProvince)

After doing some readings on LINQ documentation, I found it's equivalent LINQ code using let.
model.CountryRegionsList 
     = (from country in _context.CountryRegions
       let subQuery = (from stateprovince in _context.StateProvinces
                      select stateprovince.CountryRegionCode).Distinct()
       where subQuery.Contains(country.CountryRegionCode)
       select country).ToList();

Sunday, February 7, 2016

ASP.NET Trigger onchange event of DropDownList control inside a GridView using jQuery.

There was a question in a forum if how can we trigger an onchange event of a DropDownList control inside a GridView template field. This time using unobtrusive approach. So in order to understand a bit further, the GridView control when rendered to the browser becomes a table element while DropDownList becomes a Select control.
So, to trigger the event we need to traverse the GridView control then find the Select control and attach a change event. Here's a solution using jQuery.
HTML Markup:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<asp:GridView ID="gvItem" runat="server" AutoGenerateColumns="False">
        <Columns>
            <asp:BoundField DataField="ID" HeaderText="ID" />
            <asp:BoundField DataField="ProductName" HeaderText="ProductName" />
            <asp:TemplateField HeaderText="Time Slot">
                <ItemTemplate> 
                    <asp:DropDownList ID="Time_Slot" runat ="server">
                        <asp:ListItem Selected="True" Value="0">Select...</asp:ListItem>
                        <asp:ListItem Value="1">8:00</asp:ListItem>
                        <asp:ListItem Value="2">9:00</asp:ListItem>
                        <asp:ListItem Value="3">10:00</asp:ListItem>
                        <asp:ListItem Value="4">11:00</asp:ListItem>
                        <asp:ListItem Value="5">12:00</asp:ListItem>
                        <asp:ListItem Value="6">1:00</asp:ListItem>
                        <asp:ListItem Value="7">2:00</asp:ListItem>
                        <asp:ListItem Value="8">3:00</asp:ListItem>
                        <asp:ListItem Value="9">4:00</asp:ListItem>
                    </asp:DropDownList> 
                </ItemTemplate> 
            </asp:TemplateField>
        </Columns>      
    </asp:GridView>

jQuery code:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$(document).ready(function() {
    $("#<%=gvItem.ClientID%> tr").each(function(index) {
        if ($(this) != undefined) {
            var temp = $(this).find("select").change(function() {
                if ($(this).children(":selected").html().toString().indexOf("Select") == -1) {
                    alert("Selected order time: " + $(this).children(":selected").html());
                }
            });
        }
    });
});

Screenshot:

Thursday, February 4, 2016

ASP.NET MVC 5 Client-Side Form Validation using jQuery and Bootstrap with Model class

Here's a simple client side validation in ASP.NET MVC 5. By default, the application's unobtrusive validation has been set to true in web.config file. For this demo, I did not include a saving process to database. I just added a simple view to indicate a success if the model passed to the controller is valid. See files and screenshots below:

Registration.cs (This should be created inside the Model folder)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Registration
    {
        [Required(ErrorMessage = "You must provide your first name")]
        [Display(Name = "First Name")]
        public string FirstName { get; set; }
 
        [Required(ErrorMessage = "You must provide your last name")]
        [Display(Name = "Last Name")]
        public string LastName { get; set; }
 
        [Required(ErrorMessage = "You must provide your middle name")]
        [Display(Name = "Middle Name")]
        public string MiddleName { get; set; }
 
        [Required(ErrorMessage = "You must provide your email address")]
        [Display(Name = "E-Mail address")]
        [DataType(DataType.EmailAddress)]
        [EmailAddress]
        public string EmailAddress { get; set; }
 
        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }
 
        [Required]
        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        [System.ComponentModel.DataAnnotations.CompareAttribute("Password", ErrorMessage = "The password and confirmation password do not match.")]
        public string ConfirmPasword { get; set; }
    }

HomeController.cs
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
 
        [HttpPost]
        public ActionResult Index(Registration registration)
        {
            if (ModelState.IsValid)
            {
                return RedirectToAction("RegistrationSuccess");
            }
 
            return View();           
        }
 
        public ActionResult RegistrationSuccess()
        {
            return View();
        }
    }

Index.cshtml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
@{
    ViewBag.Title = "Home Page";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
 
@model MVCFormValidation.Models.Registration
 
<div class="row">       
 
    @using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "frmInput", @class = "form-horizontal" }))
    {           @Html.AntiForgeryToken()
                @Html.ValidationSummary(false)
                <div class="form-group">
                    @Html.LabelFor(m => m.FirstName, new { @class = "control-label col-md-2" })
                    <div class="col-md-10">
                        @Html.TextBoxFor(m => m.FirstName, new { @class = "form-control", @id = "fname", @name = "fname" })
                        @Html.ValidationMessageFor(m => m.FirstName, null)
                    </div>                   
                </div>
                <div class="form-group">
                    @Html.LabelFor(m => m.MiddleName, new { @class = "control-label col-md-2" })
                    <div class="col-md-10">
                        @Html.TextBoxFor(m => m.MiddleName, new { @class = "form-control", @id = "mname", @name = "mname" })       
                        @Html.ValidationMessageFor(m => m.MiddleName)                 
                    </div>
                </div>
                <div class="form-group">
                    <label for="lname" class="control-label col-md-2">Last Name:</label>
                    <div class="col-md-10">
                        @Html.TextBoxFor(m => m.LastName, new { @class = "form-control", @id = "lname", @name = "lname" }) 
                        @Html.ValidationMessageFor(m => m.LastName)   
                    </div>
                </div>
                <div class="form-group">
                    <label class="control-label col-md-2" for="email">Email:</label>
                    <div class="col-md-10" >
                        @Html.TextBoxFor(m => m.EmailAddress, new { @class = "form-control", @id = "email", @name = "email" })
                        @Html.ValidationMessageFor(m => m.EmailAddress) 
                    </div>
                </div>
                <div class="form-group">
                    <label for="Password" class="control-label col-md-2">Password</label>
                    <div class="col-md-10">
                        @Html.PasswordFor(m => m.Password, new { @class = "form-control", @id = "password", @name = "password" })
                        @Html.ValidationMessageFor(m => m.Password)   
                    </div>
                </div>
                <div class="form-group">
                    <label for="ConfirmPassword" class="control-label col-md-2">Confirm Password</label>
                    <div class="col-md-10">
                        @Html.PasswordFor(m => m.ConfirmPasword, new { @class = "form-control", @id = "confirmpassword", @name = "confirmpassword" })
                        @Html.ValidationMessageFor(m => m.ConfirmPasword)    
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-sm-offset-2 col-md-10">
                        <button type="submit" class="btn btn-primary">Register</button>
                        <button type="button" class="btn">Cancel</button>
                    </div>
                </div>
    }
</div>

CustomBootstrapValidation.js (This should be created inside the Scripts folder
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//bootstrap styling 3.x 
$(function () {
    // set formatting for validation summary
    $('.validation-summary-errors').each(function () {
        $(this).addClass('alert');
        $(this).addClass('alert-danger');
    });
 
    $("#frmInput").submit(function () {
        if ($(this).valid()) {
            $(this).find('div.form-group').each(function () {
                if ($(this).find('span.field-validation-error').length == 0) {
                    $(this).removeClass('has-error');
                    $(this).addClass('has-success');
                }
            });
        }
        else {
            $(this).find('div.form-group').each(function () {
                if ($(this).find('span.field-validation-error').length > 0) {
                    $(this).removeClass('has-success');
                    $(this).addClass('has-error');
                }
            });
            $('.validation-summary-errors').each(function () {
                if ($(this).hasClass('alert-danger') == false) {
                    $(this).addClass('alert');
                    $(this).addClass('alert-danger');
                }
            });
        }
    });
});
 
/* set defaults */
var page = function () {
    //Update the validator
    $.validator.setDefaults({
        highlight: function (element) {
            $(element).closest(".form-group").addClass("has-error");
            $(element).closest(".form-group").removeClass("has-success");
        },
        unhighlight: function (element) {
            $(element).closest(".form-group").removeClass("has-error");
            $(element).closest(".form-group").addClass("has-success");
        }
    });
}();

Screenshots:
Note: Make sure to bundle the external javascript file in BundleConfig.cs and Render it in Layout.cshtml.