I'm not a big fan of the ASPNETDB framework - seems needlessly complicated while still not doing many things that you want from your membership system.
But if you have to use it, one thing that really bugs me is that it doesn't have a simple way to remotely manage the users and roles. Here's a tool to lighten the load, a WinForms GUI app: http://sourceforge.net/projects/aspnetdb/
DaddyCode Team Blog
C# , ASP.NET, MVC, SQL, Sharepoint, JQuery and nowt else from a Web Developer in Leeds
6 Sept 2012
5 Sept 2012
IE, jquery, migrating from live to on for click events
Had a bit of "fun" today migrating from using jquery live() to on(). I had a bit of code like this:
Knowing that we should now use the on() function instead, I changed it to:
This seemed to work OK until I got a bug report that it wasn't working in IE8 and lower. Took a while to work it out, but turns out you can't attach a click handler to the window object in IE before IE9. Therefore the workaround was to attach to document instead:
$('.BizCard.selectable').live('click', function () { blah; });
Knowing that we should now use the on() function instead, I changed it to:
$(window).on('click', '.BizCard.selectable', function () { blah; });
This seemed to work OK until I got a bug report that it wasn't working in IE8 and lower. Took a while to work it out, but turns out you can't attach a click handler to the window object in IE before IE9. Therefore the workaround was to attach to document instead:
$(document).on('click', '.BizCard.selectable', function () { blah; });
An aide-memoire on setting cookies, reading cookies with jQuery
Assuming we use jquery.cookie.js, to SET a boolean cookie flag:
$.cookie("AutoShow_" + handle, isExpanding ? 'true' : 'false');
and to read it back
var shouldShow = /true/i.test($.cookie("AutoShow_" + handle));
15 Aug 2012
Allow MVC to work on ASP.NET 4 / IIS7 with runAllManagedModulesForAllRequests set FALSE
In pipeline mode on IIS 7, all requests for content (including requests for static files) play through the ASP.NET handler unless you set runAllManagedModulesForAllRequests to false in the <system .webserver> part of web.config.
Unfortunately by default that stops MVC 3 working because MVC urls do not have a file extension to give IIS a clue what to do.
Well cheer up, cos MS have issued a hotfix. Woop!
http://support.microsoft.com/kb/980368
For extra info see http://blogs.msdn.com/b/tmarq/archive/2010/04/01/asp-net-4-0-enables-routing-of-extensionless-urls-without-impacting-static-requests.aspx
Unfortunately by default that stops MVC 3 working because MVC urls do not have a file extension to give IIS a clue what to do.
Well cheer up, cos MS have issued a hotfix. Woop!
http://support.microsoft.com/kb/980368
For extra info see http://blogs.msdn.com/b/tmarq/archive/2010/04/01/asp-net-4-0-enables-routing-of-extensionless-urls-without-impacting-static-requests.aspx
9 Aug 2012
Visual Studio RegEx for converting old MVC Views to Razor format
This won't fix everything, but does help a lot with converting your old MVC Views to Razor format.
Basically this is RegEx replacement pattern for use in the Visual Studio Find and Replace dialog, for converting out all the old <%: blah %> tags.
Find what:
Replace with:
Don't forget to Use Regular Expressions in the Find Options.
Some of the resultant code won't work until you put brackets round it e.g. @blah blah needs to be @(blah blah)
Don't forget you may need to convert <%= blah %> tags too - perhaps convert them to @Html.Raw(blah)
Don't forget you may need to convert <% blah %> tags too - perhaps convert them to @{blah}
Basically this is RegEx replacement pattern for use in the Visual Studio Find and Replace dialog, for converting out all the old <%: blah %> tags.
Find what:
\<%\::b*{.#}:b*%\>
Replace with:
@\1
Don't forget to Use Regular Expressions in the Find Options.
Some of the resultant code won't work until you put brackets round it e.g. @blah blah needs to be @(blah blah)
Don't forget you may need to convert <%= blah %> tags too - perhaps convert them to @Html.Raw(blah)
Don't forget you may need to convert <% blah %> tags too - perhaps convert them to @{blah}
6 Aug 2012
Wii Skylanders USB dongle problem
Let me cut to the chase!
---
Phew, almost had a very disappointed birthday kid on my hands there... he got Skylanders for Wii for his birthday which features a plastic castle thing called a Portal Of Power. I didn't realize at first but the Portal contains a usb dongle which you plug into a USB port on the back of the Wii.
Well, I spent about half an hour trying to get the Portal to sync with the dongle, and no dice. The instructions say if the Portal's button is flashing, it hasn't synced with the dongle yet. You're supposed to press the SYNC button in the Portal's battery compartment and then press the button on the dongle to complete the handshake. Well I tried that about a million times but no dice.
Then I figured that the dongle would work on any usb socket so I tried it on my laptop - eureka moment - as soon as I plugged it in, not only did the Portal's button light go solid (indicating successful sync), but a little red light on the end of the dongle lit up. I didn't know the dongle had a light! So I started a-thinking that maybe the porblem was the usb ports on the wii.
I don't know about you, but i've had my Wii for about 5 years and have never used the USB ports before. They're open and collect dust so I blew them out. I plugged the dongle in - no red light. I wiggled the dongle around - RED LIGHT! I wiggled some more - no red light.
Well, seems like the USB ports on my Wii are a bit flakey. After a while I wiggled the dongle into a position where the light stayed on, and then gingerly left it alone. Booted up Skylanders and we got past the Sync screen for the first time.
WOOHOO - kid is happy and I can get on with my "real" job.
- The USB dongle has a tiny red LED on it that glows to show it's working.
- The USB ports on your Wii might be dusty - blow them clean.
- With the Wii on, plug in the dongle and wobble it around in the USB port until its red LED lights up and stays on.
- Boot up Skylanders, enjoy peace and quiet!
And if you're seriously bored, the backstory:
---
Phew, almost had a very disappointed birthday kid on my hands there... he got Skylanders for Wii for his birthday which features a plastic castle thing called a Portal Of Power. I didn't realize at first but the Portal contains a usb dongle which you plug into a USB port on the back of the Wii.
Well, I spent about half an hour trying to get the Portal to sync with the dongle, and no dice. The instructions say if the Portal's button is flashing, it hasn't synced with the dongle yet. You're supposed to press the SYNC button in the Portal's battery compartment and then press the button on the dongle to complete the handshake. Well I tried that about a million times but no dice.
Then I figured that the dongle would work on any usb socket so I tried it on my laptop - eureka moment - as soon as I plugged it in, not only did the Portal's button light go solid (indicating successful sync), but a little red light on the end of the dongle lit up. I didn't know the dongle had a light! So I started a-thinking that maybe the porblem was the usb ports on the wii.
I don't know about you, but i've had my Wii for about 5 years and have never used the USB ports before. They're open and collect dust so I blew them out. I plugged the dongle in - no red light. I wiggled the dongle around - RED LIGHT! I wiggled some more - no red light.
Well, seems like the USB ports on my Wii are a bit flakey. After a while I wiggled the dongle into a position where the light stayed on, and then gingerly left it alone. Booted up Skylanders and we got past the Sync screen for the first time.
WOOHOO - kid is happy and I can get on with my "real" job.
1 Aug 2012
Making Asynchronous / Concurrent calls to MVC - requests are synchronized
After a while coding in ASP.NET, I took some things for granted - the Session object for example. It's always there, so useful for storing little tidbits of stuff.
But I never pondered on the DARK SIDE OF THE SESSION, as regards its implication in MVC. Yes, I was vaguely aware that access to session data had to be synchronized (i.e. an exclusive lock placed on the session's data during access) but I didn't figure the duration of the lock. It turns out that in regular use, all MVC Controller Actions lock Session access for the duration of the request, with the reasoning that Session access could occur at any time during the request.
Therefore, if your browser makes several concurrent MVC requests - perhaps a regular View call, a polling AJAX call and an Image-Generation call - they will be run sequentially, NOT simultaneously.
Therefore, if one of your calls is slow to return, the others in the queue are held up in turn!
In old-school ASP.NET, you could turn this off at the Page level by setting EnableSessionState="false" in the @Page directive. But up til version 3, there was no equivalent in MVC apart from the radical step of disabling SessionState in the web.config file. See this post for more info on those strategies.
Well, in MVC 3 we still don't have fine-grained Sesssion control at the Action level, but we do at the Controller level, with the SessionState attribute. This allows us to say if we want to use default behaviour, ReadOnly access (concurrent reads, synchronized writes), or fully disabled Session in our Controller's Actions. With Session Disabled or ReadOnly, we have the asynchronous request ability that we desire, albeit that we have to be careful we make no calls (or at least Writes, in ReadOnly mode) to Session now that we have restricted access.
Usage is like so:
But I never pondered on the DARK SIDE OF THE SESSION, as regards its implication in MVC. Yes, I was vaguely aware that access to session data had to be synchronized (i.e. an exclusive lock placed on the session's data during access) but I didn't figure the duration of the lock. It turns out that in regular use, all MVC Controller Actions lock Session access for the duration of the request, with the reasoning that Session access could occur at any time during the request.
Therefore, if your browser makes several concurrent MVC requests - perhaps a regular View call, a polling AJAX call and an Image-Generation call - they will be run sequentially, NOT simultaneously.
Therefore, if one of your calls is slow to return, the others in the queue are held up in turn!
In old-school ASP.NET, you could turn this off at the Page level by setting EnableSessionState="false" in the @Page directive. But up til version 3, there was no equivalent in MVC apart from the radical step of disabling SessionState in the web.config file. See this post for more info on those strategies.
Well, in MVC 3 we still don't have fine-grained Sesssion control at the Action level, but we do at the Controller level, with the SessionState attribute. This allows us to say if we want to use default behaviour, ReadOnly access (concurrent reads, synchronized writes), or fully disabled Session in our Controller's Actions. With Session Disabled or ReadOnly, we have the asynchronous request ability that we desire, albeit that we have to be careful we make no calls (or at least Writes, in ReadOnly mode) to Session now that we have restricted access.
Usage is like so:
[Authorize]
[SessionState(System.Web.SessionState.SessionStateBehavior.Disabled)]
public class DocumentController : Controller
{
public ActionResult ViewDocument(int id)
{
var doc = WebApp.MainService.GetDocument(id);
if (doc == null
|| !(doc.UploadedBy == WebApp.CurrentUser.UserId
|| doc.OwnerUserId == WebApp.CurrentUser.UserId
|| WebApp.CurrentUser.IsInRole(Core.Enums.RoleType.Admin, WebApp.CurrentSite.SiteId)))
{
throw new Exception("You do not have permission to view this Document");
}
ContentDisposition cd = new ContentDisposition { Inline = true, FileName = doc.Filename };
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(DocumentService.GetSavedDocumentFileName(doc), FileTools.DetermineContentType(doc.Filename));
}
}
2 Jul 2012
A Kick-Ass Country Selector List / Country DropDownList for MVC 3 with Razor
Country List selectors on website generally suck. They especially suck when you use a UK website and "United Kingdom" is naturally at the bottom of the list because of boring old alpha-sort. What you'd ideally want is to start typing in a Country box, and the most relevant countries should appear at the top of the list.
Well, Jamie Appleseed at the Baymard Institute has a solution, which rocketh most awesomely. It's so cool it does stuff like return "Germany" at the top of the list when the user starts typing "Deutschland". That's so USABLE I want to take the code home and smooch with it all night long.
Here I provide a way to use it in MVC 3 / Razor, so you can call it very simply from your Views.
1. Get the jquery.select-to-autocomplete.js library off github and save it in your MVC site's Scripts folder.
2. Include a call to the library from your masterpage
3. In your Views / Shared / EditorTemplates folder, create a file called CountryList.cshtml and stick the following in it.
or even better, use the UIHint attribute (in System.ComponentModel.DataAnnotations) to decorate your model to use the CountryList automatically.
So in your model:
and in your view, a beautifully simple call:
Well, Jamie Appleseed at the Baymard Institute has a solution, which rocketh most awesomely. It's so cool it does stuff like return "Germany" at the top of the list when the user starts typing "Deutschland". That's so USABLE I want to take the code home and smooch with it all night long.
Here I provide a way to use it in MVC 3 / Razor, so you can call it very simply from your Views.
1. Get the jquery.select-to-autocomplete.js library off github and save it in your MVC site's Scripts folder.
2. Include a call to the library from your masterpage
<script src="@Url.Content("~/Scripts/jquery.selectToAutocomplete.js")" type="text/javascript"></script>
3. In your Views / Shared / EditorTemplates folder, create a file called CountryList.cshtml and stick the following in it.
@model string
@{
var controlId = ViewData.TemplateInfo.HtmlFieldPrefix.Replace(".", HtmlHelper.IdAttributeDotReplacement);
}
<script id="scriptCountryList" language="javascript">
$(function () {
if ($('#@controlId').val() != '@Model')
{
$('#@controlId').val('@Model');
}
$('#@controlId').selectToAutocomplete();
});
</script>
<select name="@ViewData.TemplateInfo.HtmlFieldPrefix" id="@controlId" autofocus="autofocus" autocorrect="off" autocomplete="off">
<option value=""></option>
<option value="Afghanistan" data-alternative-spellings="AF افغانستان">Afghanistan</option>
<option value="Åland Islands" data-alternative-spellings="AX Aaland Aland" data-relevancy-booster="0.5">Åland Islands</option>
<option value="Albania" data-alternative-spellings="AL">Albania</option>
<option value="Algeria" data-alternative-spellings="DZ الجزائر">Algeria</option>
<option value="American Samoa" data-alternative-spellings="AS" data-relevancy-booster="0.5">American Samoa</option>
<option value="Andorra" data-alternative-spellings="AD" data-relevancy-booster="0.5">Andorra</option>
<option value="Angola" data-alternative-spellings="AO">Angola</option>
<option value="Anguilla" data-alternative-spellings="AI" data-relevancy-booster="0.5">Anguilla</option>
<option value="Antarctica" data-alternative-spellings="AQ" data-relevancy-booster="0.5">Antarctica</option>
<option value="Antigua And Barbuda" data-alternative-spellings="AG" data-relevancy-booster="0.5">Antigua And Barbuda</option>
<option value="Argentina" data-alternative-spellings="AR">Argentina</option>
<option value="Armenia" data-alternative-spellings="AM Հայաստան">Armenia</option>
<option value="Aruba" data-alternative-spellings="AW" data-relevancy-booster="0.5">Aruba</option>
<option value="Australia" data-alternative-spellings="AU" data-relevancy-booster="1.5">Australia</option>
<option value="Austria" data-alternative-spellings="AT Österreich Osterreich Oesterreich ">Austria</option>
<option value="Azerbaijan" data-alternative-spellings="AZ">Azerbaijan</option>
<option value="Bahamas" data-alternative-spellings="BS">Bahamas</option>
<option value="Bahrain" data-alternative-spellings="BH البحرين">Bahrain</option>
<option value="Bangladesh" data-alternative-spellings="BD বাংলাদেশ" data-relevancy-booster="2">Bangladesh</option>
<option value="Barbados" data-alternative-spellings="BB">Barbados</option>
<option value="Belarus" data-alternative-spellings="BY Беларусь">Belarus</option>
<option value="Belgium" data-alternative-spellings="BE België Belgie Belgien Belgique" data-relevancy-booster="1.5">Belgium</option>
<option value="Belize" data-alternative-spellings="BZ">Belize</option>
<option value="Benin" data-alternative-spellings="BJ">Benin</option>
<option value="Bermuda" data-alternative-spellings="BM" data-relevancy-booster="0.5">Bermuda</option>
<option value="Bhutan" data-alternative-spellings="BT भूटान">Bhutan</option>
<option value="Bolivia" data-alternative-spellings="BO">Bolivia</option>
<option value="Bonaire, Sint Eustatius and Saba" data-alternative-spellings="BQ">Bonaire, Sint Eustatius and Saba</option>
<option value="Bosnia and Herzegovina" data-alternative-spellings="BA Босна и Херцеговина">Bosnia and Herzegovina</option>
<option value="Botswana" data-alternative-spellings="BW">Botswana</option>
<option value="Bouvet Island" data-alternative-spellings="BV">Bouvet Island</option>
<option value="Brazil" data-alternative-spellings="BR Brasil" data-relevancy-booster="2">Brazil</option>
<option value="British Indian Ocean Territory" data-alternative-spellings="IO">British Indian Ocean Territory</option>
<option value="Brunei Darussalam" data-alternative-spellings="BN">Brunei Darussalam</option>
<option value="Bulgaria" data-alternative-spellings="BG България">Bulgaria</option>
<option value="Burkina Faso" data-alternative-spellings="BF">Burkina Faso</option>
<option value="Burundi" data-alternative-spellings="BI">Burundi</option>
<option value="Cambodia" data-alternative-spellings="KH កម្ពុជា">Cambodia</option>
<option value="Cameroon" data-alternative-spellings="CM">Cameroon</option>
<option value="Canada" data-alternative-spellings="CA" data-relevancy-booster="2">Canada</option>
<option value="Cape Verde" data-alternative-spellings="CV Cabo">Cape Verde</option>
<option value="Cayman Islands" data-alternative-spellings="KY" data-relevancy-booster="0.5">Cayman Islands</option>
<option value="Central African Republic" data-alternative-spellings="CF">Central African Republic</option>
<option value="Chad" data-alternative-spellings="TD تشاد Tchad">Chad</option>
<option value="Chile" data-alternative-spellings="CL">Chile</option>
<option value="China" data-relevancy-booster="3.5" data-alternative-spellings="CN Zhongguo Zhonghua Peoples Republic 中国/中华">China</option>
<option value="Christmas Island" data-alternative-spellings="CX" data-relevancy-booster="0.5">Christmas Island</option>
<option value="Cocos (Keeling) Islands" data-alternative-spellings="CC" data-relevancy-booster="0.5">Cocos (Keeling) Islands</option>
<option value="Colombia" data-alternative-spellings="CO">Colombia</option>
<option value="Comoros" data-alternative-spellings="KM جزر القمر">Comoros</option>
<option value="Congo" data-alternative-spellings="CG">Congo</option>
<option value="Congo, the Democratic Republic of the" data-alternative-spellings="CD Congo-Brazzaville Repubilika ya Kongo">Congo, the Democratic Republic of the</option>
<option value="Cook Islands" data-alternative-spellings="CK" data-relevancy-booster="0.5">Cook Islands</option>
<option value="Costa Rica" data-alternative-spellings="CR">Costa Rica</option>
<option value="Côte d'Ivoire" data-alternative-spellings="CI Cote dIvoire">Côte d'Ivoire</option>
<option value="Croatia" data-alternative-spellings="HR Hrvatska">Croatia</option>
<option value="Cuba" data-alternative-spellings="CU">Cuba</option>
<option value="Curaçao" data-alternative-spellings="CW Curacao">Curaçao</option>
<option value="Cyprus" data-alternative-spellings="CY Κύπρος Kýpros Kıbrıs">Cyprus</option>
<option value="Czech Republic" data-alternative-spellings="CZ Česká Ceska">Czech Republic</option>
<option value="Denmark" data-alternative-spellings="DK Danmark" data-relevancy-booster="1.5">Denmark</option>
<option value="Djibouti" data-alternative-spellings="DJ جيبوتي Jabuuti Gabuuti">Djibouti</option>
<option value="Dominica" data-alternative-spellings="DM Dominique" data-relevancy-booster="0.5">Dominica</option>
<option value="Dominican Republic" data-alternative-spellings="DO">Dominican Republic</option>
<option value="Ecuador" data-alternative-spellings="EC">Ecuador</option>
<option value="Egypt" data-alternative-spellings="EG" data-relevancy-booster="1.5">Egypt</option>
<option value="El Salvador" data-alternative-spellings="SV">El Salvador</option>
<option value="Equatorial Guinea" data-alternative-spellings="GQ">Equatorial Guinea</option>
<option value="Eritrea" data-alternative-spellings="ER إرتريا ኤርትራ">Eritrea</option>
<option value="Estonia" data-alternative-spellings="EE Eesti">Estonia</option>
<option value="Ethiopia" data-alternative-spellings="ET ኢትዮጵያ">Ethiopia</option>
<option value="Falkland Islands (Malvinas)" data-alternative-spellings="FK" data-relevancy-booster="0.5">Falkland Islands (Malvinas)</option>
<option value="Faroe Islands" data-alternative-spellings="FO Føroyar Færøerne" data-relevancy-booster="0.5">Faroe Islands</option>
<option value="Fiji" data-alternative-spellings="FJ Viti फ़िजी">Fiji</option>
<option value="Finland" data-alternative-spellings="FI Suomi">Finland</option>
<option value="France" data-alternative-spellings="FR République française" data-relevancy-booster="2.5">France</option>
<option value="French Guiana" data-alternative-spellings="GF">French Guiana</option>
<option value="French Polynesia" data-alternative-spellings="PF Polynésie française">French Polynesia</option>
<option value="French Southern Territories" data-alternative-spellings="TF">French Southern Territories</option>
<option value="Gabon" data-alternative-spellings="GA République Gabonaise">Gabon</option>
<option value="Gambia" data-alternative-spellings="GM">Gambia</option>
<option value="Georgia" data-alternative-spellings="GE საქართველო">Georgia</option>
<option value="Germany" data-alternative-spellings="DE Bundesrepublik Deutschland" data-relevancy-booster="3">Germany</option>
<option value="Ghana" data-alternative-spellings="GH">Ghana</option>
<option value="Gibraltar" data-alternative-spellings="GI" data-relevancy-booster="0.5">Gibraltar</option>
<option value="Greece" data-alternative-spellings="GR Ελλάδα" data-relevancy-booster="1.5">Greece</option>
<option value="Greenland" data-alternative-spellings="GL grønland" data-relevancy-booster="0.5">Greenland</option>
<option value="Grenada" data-alternative-spellings="GD">Grenada</option>
<option value="Guadeloupe" data-alternative-spellings="GP">Guadeloupe</option>
<option value="Guam" data-alternative-spellings="GU">Guam</option>
<option value="Guatemala" data-alternative-spellings="GT">Guatemala</option>
<option value="Guernsey" data-alternative-spellings="GG" data-relevancy-booster="0.5">Guernsey</option>
<option value="Guinea" data-alternative-spellings="GN">Guinea</option>
<option value="Guinea-Bissau" data-alternative-spellings="GW">Guinea-Bissau</option>
<option value="Guyana" data-alternative-spellings="GY">Guyana</option>
<option value="Haiti" data-alternative-spellings="HT">Haiti</option>
<option value="Heard Island and McDonald Islands" data-alternative-spellings="HM">Heard Island and McDonald Islands</option>
<option value="Holy See (Vatican City State)" data-alternative-spellings="VA" data-relevancy-booster="0.5">Holy See (Vatican City State)</option>
<option value="Honduras" data-alternative-spellings="HN">Honduras</option>
<option value="Hong Kong" data-alternative-spellings="HK 香港">Hong Kong</option>
<option value="Hungary" data-alternative-spellings="HU Magyarország">Hungary</option>
<option value="Iceland" data-alternative-spellings="IS Island">Iceland</option>
<option value="India" data-alternative-spellings="IN भारत गणराज्य Hindustan" data-relevancy-booster="3">India</option>
<option value="Indonesia" data-alternative-spellings="ID" data-relevancy-booster="2">Indonesia</option>
<option value="Iran, Islamic Republic of" data-alternative-spellings="IR ایران">Iran, Islamic Republic of</option>
<option value="Iraq" data-alternative-spellings="IQ العراق">Iraq</option>
<option value="Ireland" data-alternative-spellings="IE Éire" data-relevancy-booster="1.2">Ireland</option>
<option value="Isle of Man" data-alternative-spellings="IM" data-relevancy-booster="0.5">Isle of Man</option>
<option value="Israel" data-alternative-spellings="IL إسرائيل ישראל">Israel</option>
<option value="Italy" data-alternative-spellings="IT Italia" data-relevancy-booster="2">Italy</option>
<option value="Jamaica" data-alternative-spellings="JM">Jamaica</option>
<option value="Japan" data-alternative-spellings="JP Nippon Nihon 日本" data-relevancy-booster="2.5">Japan</option>
<option value="Jersey" data-alternative-spellings="JE" data-relevancy-booster="0.5">Jersey</option>
<option value="Jordan" data-alternative-spellings="JO الأردن">Jordan</option>
<option value="Kazakhstan" data-alternative-spellings="KZ Қазақстан Казахстан">Kazakhstan</option>
<option value="Kenya" data-alternative-spellings="KE">Kenya</option>
<option value="Kiribati" data-alternative-spellings="KI">Kiribati</option>
<option value="Korea, Democratic People's Republic of" data-alternative-spellings="KP North Korea">Korea, Democratic People's Republic of</option>
<option value="Korea, Republic of" data-alternative-spellings="KR South Korea" data-relevancy-booster="1.5">Korea, Republic of</option>
<option value="Kuwait" data-alternative-spellings="KW الكويت">Kuwait</option>
<option value="Kyrgyzstan" data-alternative-spellings="KG Кыргызстан">Kyrgyzstan</option>
<option value="Lao People's Democratic Republic" data-alternative-spellings="LA">Lao People's Democratic Republic</option>
<option value="Latvia" data-alternative-spellings="LV Latvija">Latvia</option>
<option value="Lebanon" data-alternative-spellings="LB لبنان">Lebanon</option>
<option value="Lesotho" data-alternative-spellings="LS">Lesotho</option>
<option value="Liberia" data-alternative-spellings="LR">Liberia</option>
<option value="Libyan Arab Jamahiriya" data-alternative-spellings="LY ليبيا">Libyan Arab Jamahiriya</option>
<option value="Liechtenstein" data-alternative-spellings="LI">Liechtenstein</option>
<option value="Lithuania" data-alternative-spellings="LT Lietuva">Lithuania</option>
<option value="Luxembourg" data-alternative-spellings="LU">Luxembourg</option>
<option value="Macao" data-alternative-spellings="MO">Macao</option>
<option value="Macedonia, The Former Yugoslav Republic Of" data-alternative-spellings="MK Македонија">Macedonia, The Former Yugoslav Republic Of</option>
<option value="Madagascar" data-alternative-spellings="MG Madagasikara">Madagascar</option>
<option value="Malawi" data-alternative-spellings="MW">Malawi</option>
<option value="Malaysia" data-alternative-spellings="MY">Malaysia</option>
<option value="Maldives" data-alternative-spellings="MV">Maldives</option>
<option value="Mali" data-alternative-spellings="ML">Mali</option>
<option value="Malta" data-alternative-spellings="MT">Malta</option>
<option value="Marshall Islands" data-alternative-spellings="MH" data-relevancy-booster="0.5">Marshall Islands</option>
<option value="Martinique" data-alternative-spellings="MQ">Martinique</option>
<option value="Mauritania" data-alternative-spellings="MR الموريتانية">Mauritania</option>
<option value="Mauritius" data-alternative-spellings="MU">Mauritius</option>
<option value="Mayotte" data-alternative-spellings="YT">Mayotte</option>
<option value="Mexico" data-alternative-spellings="MX Mexicanos" data-relevancy-booster="1.5">Mexico</option>
<option value="Micronesia, Federated States of" data-alternative-spellings="FM">Micronesia, Federated States of</option>
<option value="Moldova, Republic of" data-alternative-spellings="MD">Moldova, Republic of</option>
<option value="Monaco" data-alternative-spellings="MC">Monaco</option>
<option value="Mongolia" data-alternative-spellings="MN Mongγol ulus Монгол улс">Mongolia</option>
<option value="Montenegro" data-alternative-spellings="ME">Montenegro</option>
<option value="Montserrat" data-alternative-spellings="MS" data-relevancy-booster="0.5">Montserrat</option>
<option value="Morocco" data-alternative-spellings="MA المغرب">Morocco</option>
<option value="Mozambique" data-alternative-spellings="MZ Moçambique">Mozambique</option>
<option value="Myanmar" data-alternative-spellings="MM">Myanmar</option>
<option value="Namibia" data-alternative-spellings="NA Namibië">Namibia</option>
<option value="Nauru" data-alternative-spellings="NR Naoero" data-relevancy-booster="0.5">Nauru</option>
<option value="Nepal" data-alternative-spellings="NP नेपाल">Nepal</option>
<option value="Netherlands" data-alternative-spellings="NL Holland Nederland" data-relevancy-booster="1.5">Netherlands</option>
<option value="New Caledonia" data-alternative-spellings="NC" data-relevancy-booster="0.5">New Caledonia</option>
<option value="New Zealand" data-alternative-spellings="NZ Aotearoa">New Zealand</option>
<option value="Nicaragua" data-alternative-spellings="NI">Nicaragua</option>
<option value="Niger" data-alternative-spellings="NE Nijar">Niger</option>
<option value="Nigeria" data-alternative-spellings="NG Nijeriya Naíjíríà" data-relevancy-booster="1.5">Nigeria</option>
<option value="Niue" data-alternative-spellings="NU" data-relevancy-booster="0.5">Niue</option>
<option value="Norfolk Island" data-alternative-spellings="NF" data-relevancy-booster="0.5">Norfolk Island</option>
<option value="Northern Mariana Islands" data-alternative-spellings="MP" data-relevancy-booster="0.5">Northern Mariana Islands</option>
<option value="Norway" data-alternative-spellings="NO Norge Noreg" data-relevancy-booster="1.5">Norway</option>
<option value="Oman" data-alternative-spellings="OM عمان">Oman</option>
<option value="Pakistan" data-alternative-spellings="PK پاکستان" data-relevancy-booster="2">Pakistan</option>
<option value="Palau" data-alternative-spellings="PW" data-relevancy-booster="0.5">Palau</option>
<option value="Palestinian Territory, Occupied" data-alternative-spellings="PS فلسطين">Palestinian Territory, Occupied</option>
<option value="Panama" data-alternative-spellings="PA">Panama</option>
<option value="Papua New Guinea" data-alternative-spellings="PG">Papua New Guinea</option>
<option value="Paraguay" data-alternative-spellings="PY">Paraguay</option>
<option value="Peru" data-alternative-spellings="PE">Peru</option>
<option value="Philippines" data-alternative-spellings="PH Pilipinas" data-relevancy-booster="1.5">Philippines</option>
<option value="Pitcairn" data-alternative-spellings="PN" data-relevancy-booster="0.5">Pitcairn</option>
<option value="Poland" data-alternative-spellings="PL Polska" data-relevancy-booster="1.25">Poland</option>
<option value="Portugal" data-alternative-spellings="PT Portuguesa" data-relevancy-booster="1.5">Portugal</option>
<option value="Puerto Rico" data-alternative-spellings="PR">Puerto Rico</option>
<option value="Qatar" data-alternative-spellings="QA قطر">Qatar</option>
<option value="Réunion" data-alternative-spellings="RE Reunion">Réunion</option>
<option value="Romania" data-alternative-spellings="RO Rumania Roumania România">Romania</option>
<option value="Russian Federation" data-alternative-spellings="RU Rossiya Российская Россия" data-relevancy-booster="2.5">Russian Federation</option>
<option value="Rwanda" data-alternative-spellings="RW">Rwanda</option>
<option value="Saint Barthélemy" data-alternative-spellings="BL St. Barthelemy">Saint Barthélemy</option>
<option value="Saint Helena" data-alternative-spellings="SH St.">Saint Helena</option>
<option value="Saint Kitts and Nevis" data-alternative-spellings="KN St.">Saint Kitts and Nevis</option>
<option value="Saint Lucia" data-alternative-spellings="LC St.">Saint Lucia</option>
<option value="Saint Martin (French Part)" data-alternative-spellings="MF St.">Saint Martin (French Part)</option>
<option value="Saint Pierre and Miquelon" data-alternative-spellings="PM St.">Saint Pierre and Miquelon</option>
<option value="Saint Vincent and the Grenadines" data-alternative-spellings="VC St.">Saint Vincent and the Grenadines</option>
<option value="Samoa" data-alternative-spellings="WS">Samoa</option>
<option value="San Marino" data-alternative-spellings="SM">San Marino</option>
<option value="Sao Tome and Principe" data-alternative-spellings="ST">Sao Tome and Principe</option>
<option value="Saudi Arabia" data-alternative-spellings="SA السعودية">Saudi Arabia</option>
<option value="Senegal" data-alternative-spellings="SN Sénégal">Senegal</option>
<option value="Serbia" data-alternative-spellings="RS Србија Srbija">Serbia</option>
<option value="Seychelles" data-alternative-spellings="SC" data-relevancy-booster="0.5">Seychelles</option>
<option value="Sierra Leone" data-alternative-spellings="SL">Sierra Leone</option>
<option value="Singapore" data-alternative-spellings="SG Singapura சிங்கப்பூர் குடியரசு 新加坡共和国">Singapore</option>
<option value="Sint Maarten (Dutch Part)" data-alternative-spellings="SX">Sint Maarten (Dutch Part)</option>
<option value="Slovakia" data-alternative-spellings="SK Slovenská Slovensko">Slovakia</option>
<option value="Slovenia" data-alternative-spellings="SI Slovenija">Slovenia</option>
<option value="Solomon Islands" data-alternative-spellings="SB">Solomon Islands</option>
<option value="Somalia" data-alternative-spellings="SO الصومال">Somalia</option>
<option value="South Africa" data-alternative-spellings="ZA RSA Suid-Afrika">South Africa</option>
<option value="South Georgia and the South Sandwich Islands" data-alternative-spellings="GS">South Georgia and the South Sandwich Islands</option>
<option value="South Sudan" data-alternative-spellings="SS">South Sudan</option>
<option value="Spain" data-alternative-spellings="ES España" data-relevancy-booster="2">Spain</option>
<option value="Sri Lanka" data-alternative-spellings="LK ශ්රී ලංකා இலங்கை Ceylon">Sri Lanka</option>
<option value="Sudan" data-alternative-spellings="SD السودان">Sudan</option>
<option value="Suriname" data-alternative-spellings="SR शर्नम् Sarnam Sranangron">Suriname</option>
<option value="Svalbard and Jan Mayen" data-alternative-spellings="SJ" data-relevancy-booster="0.5">Svalbard and Jan Mayen</option>
<option value="Swaziland" data-alternative-spellings="SZ weSwatini Swatini Ngwane">Swaziland</option>
<option value="Sweden" data-alternative-spellings="SE Sverige" data-relevancy-booster="1.5">Sweden</option>
<option value="Switzerland" data-alternative-spellings="CH Swiss Confederation Schweiz Suisse Svizzera Svizra" data-relevancy-booster="1.5">Switzerland</option>
<option value="Syrian Arab Republic" data-alternative-spellings="SY Syria سورية">Syrian Arab Republic</option>
<option value="Taiwan, Province of China" data-alternative-spellings="TW 台灣 臺灣">Taiwan, Province of China</option>
<option value="Tajikistan" data-alternative-spellings="TJ Тоҷикистон Toçikiston">Tajikistan</option>
<option value="Tanzania, United Republic of" data-alternative-spellings="TZ">Tanzania, United Republic of</option>
<option value="Thailand" data-alternative-spellings="TH ประเทศไทย Prathet Thai">Thailand</option>
<option value="Timor-Leste" data-alternative-spellings="TL">Timor-Leste</option>
<option value="Togo" data-alternative-spellings="TG Togolese">Togo</option>
<option value="Tokelau" data-alternative-spellings="TK" data-relevancy-booster="0.5">Tokelau</option>
<option value="Tonga" data-alternative-spellings="TO">Tonga</option>
<option value="Trinidad and Tobago" data-alternative-spellings="TT">Trinidad and Tobago</option>
<option value="Tunisia" data-alternative-spellings="TN تونس">Tunisia</option>
<option value="Turkey" data-alternative-spellings="TR Türkiye Turkiye">Turkey</option>
<option value="Turkmenistan" data-alternative-spellings="TM Türkmenistan">Turkmenistan</option>
<option value="Turks and Caicos Islands" data-alternative-spellings="TC" data-relevancy-booster="0.5">Turks and Caicos Islands</option>
<option value="Tuvalu" data-alternative-spellings="TV" data-relevancy-booster="0.5">Tuvalu</option>
<option value="Uganda" data-alternative-spellings="UG">Uganda</option>
<option value="Ukraine" data-alternative-spellings="UA Ukrayina Україна">Ukraine</option>
<option value="United Arab Emirates" data-alternative-spellings="AE UAE الإمارات">United Arab Emirates</option>
<option value="United Kingdom" data-alternative-spellings="GB Great Britain England UK Wales Scotland Northern Ireland" data-relevancy-booster="2.5">United Kingdom</option>
<option value="United States" data-relevancy-booster="3.5" data-alternative-spellings="US USA United States of America">United States</option>
<option value="United States Minor Outlying Islands" data-alternative-spellings="UM">United States Minor Outlying Islands</option>
<option value="Uruguay" data-alternative-spellings="UY">Uruguay</option>
<option value="Uzbekistan" data-alternative-spellings="UZ Ўзбекистон O'zbekstan O‘zbekiston">Uzbekistan</option>
<option value="Vanuatu" data-alternative-spellings="VU">Vanuatu</option>
<option value="Venezuela" data-alternative-spellings="VE">Venezuela</option>
<option value="Vietnam" data-alternative-spellings="VN Việt Nam" data-relevancy-booster="1.5">Vietnam</option>
<option value="Virgin Islands, British" data-alternative-spellings="VG" data-relevancy-booster="0.5">Virgin Islands, British</option>
<option value="Virgin Islands, U.S." data-alternative-spellings="VI" data-relevancy-booster="0.5">Virgin Islands, U.S.</option>
<option value="Wallis and Futuna" data-alternative-spellings="WF" data-relevancy-booster="0.5">Wallis and Futuna</option>
<option value="Western Sahara" data-alternative-spellings="EH لصحراء الغربية">Western Sahara</option>
<option value="Yemen" data-alternative-spellings="YE اليمن">Yemen</option>
<option value="Zambia" data-alternative-spellings="ZM">Zambia</option>
<option value="Zimbabwe" data-alternative-spellings="ZW">Zimbabwe</option>
</select>
4. Simply call the CountryList from your view using the EditorFor HtmlHelper :@Html.EditorFor(model => model.UserCountry, "CountryList")
or even better, use the UIHint attribute (in System.ComponentModel.DataAnnotations) to decorate your model to use the CountryList automatically.
So in your model:
[Required(AllowEmptyStrings = false)]
[Display(Name = "Country")]
[UIHint("CountryList")]
public string UserCountry { get; set; }
and in your view, a beautifully simple call:
@Html.EditorFor(model => model.UserCountry)
28 Jun 2012
Access Denied on the Amazon MWS Scratchpad
Annoying! I was getting an Access Denied error when sending through requests on the Amazon MWS Scratchpad. I checked and rechecked I was sending through the correct Access Key, Secret Key, Marketplace ID etc.
Turns out I was on the wrong site! My Marketplace was in the UK so I have to use
https://mws.amazonservices.co.uk/scratchpad/index.html
NOT
https://mws.amazonservices.com/scratchpad/index.html
Turns out I was on the wrong site! My Marketplace was in the UK so I have to use
https://mws.amazonservices.co.uk/scratchpad/index.html
NOT
https://mws.amazonservices.com/scratchpad/index.html
20 Jun 2012
A custom ValueInjecter Injection to use with models decorated with the MVC Bind Attribute
In some cases, I would like to use the Omu ValueInjecter's InjectFrom() to only copy source properties which have been marked for inclusion by an MVC BindAttribute. So, I've developed the following Injection:
This allows me to simply define ViewModels with Bind Exclusion lists like this:
And then my Controller's Update Action would look like this:
Using that technique, the end user can update the User object's Name property without being able to overwrite the IsSuperUser property.
NOTE
It's true that MVC's UpdateModel() method obeys BindAttribute inclusion/exclusions found on the target object, so you may ask why we need to use ValueInjecter at all. However, that would necessitate the target object type to contain the Bind attributes. In our case, we want the source and target to be of different types, so that the Source (ViewModel) type has the Bind exclusions, leaving the Target type (Source's super-type) undecorated. This approach allows us to declare thin ViewModels based on underlying domain classes without having to slavishly modify our VM definitions every time the superclass definition changes.
Incidentally, by default the BindAwareInjection uses the Bind attributes from the Source, but you can use the Target attributes instead like this:
public class BindAwareInjection : LoopValueInjection
{
public List<string> PropertiesToInclude = new List<string>();
public List<string> PropertiesToExclude = new List<string>();
public BindRuleLocationType BindRuleLocation = BindRuleLocationType.Source;
public enum BindRuleLocationType
{
Source,
Target
}
protected override void Inject(object source, object target)
{
var bindRuleObject = BindRuleLocation == BindRuleLocationType.Source ? source : target;
var bindAttributes = (BindAttribute[])bindRuleObject.GetType().GetCustomAttributes(typeof(BindAttribute), true);
foreach (var bindRule in bindAttributes)
{
if (!string.IsNullOrEmpty(bindRule.Include))
{
PropertiesToInclude = new List<string>(bindRule.Include.Split(','));
}
else if (!string.IsNullOrEmpty(bindRule.Exclude))
{
PropertiesToExclude.AddRange(bindRule.Exclude.Split(','));
}
}
base.Inject(source, target);
}
protected override bool UseSourceProp(string sourcePropName)
{
if (PropertiesToInclude.Count > 0)
{
return PropertiesToExclude.Any(prop => prop == sourcePropName);
}
else if (!PropertiesToExclude.Any(prop => prop == sourcePropName))
{
return true;
}
return false;
}
}
This allows me to simply define ViewModels with Bind Exclusion lists like this:
public class User{
public bool IsSuperUser { get; set; }
public string Name { get; set; }
}
[Bind(Exclude = "IsSuperUser")]
public class UserVM : User { }
And then my Controller's Update Action would look like this:
[HttpPost]
public ActionResult UpdateUser(UserVM model)
{
User target = Repository.GetCurrentUser();
target.InjectFrom<BindAwareInjection>(model);
return View(target);
}
Using that technique, the end user can update the User object's Name property without being able to overwrite the IsSuperUser property.
NOTE
It's true that MVC's UpdateModel() method obeys BindAttribute inclusion/exclusions found on the target object, so you may ask why we need to use ValueInjecter at all. However, that would necessitate the target object type to contain the Bind attributes. In our case, we want the source and target to be of different types, so that the Source (ViewModel) type has the Bind exclusions, leaving the Target type (Source's super-type) undecorated. This approach allows us to declare thin ViewModels based on underlying domain classes without having to slavishly modify our VM definitions every time the superclass definition changes.
Incidentally, by default the BindAwareInjection uses the Bind attributes from the Source, but you can use the Target attributes instead like this:
[HttpPost]
public ActionResult UpdateUser(UserVM model)
{
var target = Repository.GetCurrentUser();
var injection = new BindAwareInjection { BindRuleLocation = BindAwareInjection.BindRuleLocationType.Target };
target.InjectFrom(injection, model);
return View(target);
}
Subscribe to:
Posts (Atom)
If I helped you out today, you can buy me a beer below. Cheers!