2014-07-27

Attraction doesn't always mean action

So here's a really interesting story. It's a hard one to read or listen to, because it involves something that, I'd wager, most of us would rather not think about. It's about a young man who discovered he was sexually attracted to children, and how he's been struggling with this attraction all his life. A big part of his struggle is that pedophilia is something for which it is very difficult to get help. As the article states: "…they have no way to talk about these urges or how to prevent them from taking control of their lives without being considered a threat. Talk to a shrink? You risk being reported to the authorities. The scientific community is so afraid of the stigma attached to even researching pedophilia that it's barely been studied it at all." Which is why this young man has risked tarring and feathering to set up support groups, to help people who need help taking control of their lives instead of letting their urges define and control them. It's actually a pretty inspirational story about taking control and standing up for what's right, even when the wrongness is coming from your own self.

Now, here's where I'm about to get very unpopular.

Take that same story, but replace all references to sexual attraction to children, with sexual attraction to members of the same sex.

Suddenly, it goes from a story of inspiration and self-control to one worthy of derision because of its support of self-denial and giving in to homophobia.

I've seen many arguments that saying "anti-gay" is wrong because people can't change who they are, and they should be free to act on their feelings. It's the whole crux of the argument for allowing same-sex marriage: preventing discrimination based on what a person is. Yet if we were to apply the same logic to other sexual attractions that are (still) considered bad — pedophilia, bestiality, necrophilia, take your pick — we would be immediately shot down for trying to support the "sick" or "depraved" (if we weren't immediately shot for merely insinuating any kind of relationship between homosexuality and pedophilia).

So what's the difference? Attraction to children is something that, as a society, we all seem to agree is wrong — so it's ok to have laws against it and to not even think about granting legal protections and rights to those forms of relationships. And yet, it wasn't until just the past few years that the same could be said for same-sex attraction. Debate or blame whomever you wish for the existence of California's famous Proposition 8, but the fact that it passed means there was a significant number of people who, less than a decade ago, supported the idea that condoning same-sex attraction was wrong.

So, why? Why is this form of sexual attraction ok, and others aren't? What makes same-sex attraction part of a person's being, but underage attraction something that a person can and should suppress and live their lives in denial of? And what form of sexual attraction that we think is wrong today, will we be forced to bake cakes in celebration of ten years from now?

2014-07-17

MVC, JSON, and DateTime (oh my)

It's been a while since I've had a programming issue that warrants a blog post, but here's an interesting one.
First, let me set up the situation. I have an MVC project (MVC version 5.0) that communicates to RESTful services using WebAPI (version 5.1). In one particular view, I write out an object in JSON with the intent that the client can make changes to it and POST it back to an MVC action to get an HTML table back. Here's the model:

public class PaymentScheduleRequestModel {
[JsonProperty(PropertyName = "effDt", NullValueHandling = NullValueHandling.Ignore)]
public DateTime EffectiveDate { get; set; }

[JsonProperty(PropertyName = "termId", NullValueHandling = NullValueHandling.Ignore)]
public Nullable<int> ContractTermId { get; set; }

[JsonProperty(PropertyName = "billDay", NullValueHandling = NullValueHandling.Ignore)]
public int BillingDayOfMonth { get; set; }

[JsonProperty(PropertyName = "freq", NullValueHandling = NullValueHandling.Ignore)]
public PaymentScheduleFrequencyId PaymentScheduleFrequencyId { get; set; }

[JsonProperty(PropertyName = "prem", NullValueHandling = NullValueHandling.Ignore)]
public decimal TotalPremium { get; set; }
}

(Note that the JsonProperty decorators exist because the same model is used to communicate to the WebAPI service -- we are using shorter property names to lighten the payload.)

And the MVC action that is set up to process it looks like this:

[HttpPost] public async Task<ActionResult> NewPaymentSchedule(PaymentScheduleRequestModel request) { … }

To put it in JavaScript, the view has this block of code:

window.ScriptModel = @Html.Raw(Json.Encode(new {
PaymentScheduleUrl = Url.Action("NewPaymentSchedule", "Contract"),
PaymentScheduleRequestModel = new PaymentScheduleRequestModel {
ContractTermId = Model.ContractTermId,
EffectiveDate = Model.StartDate ?? DateTime.Now,
TotalPremium = 200m
}
}));

Unfortunately, Json.Encode doesn't work well with dates. This is the output that the browser sees (with line breaks added for legibility):

window.ScriptModel={
"PaymentScheduleUrl":"/Contract/NewPaymentSchedule",
"PaymentScheduleRequestModel":{
"EffectiveDate":"\/Date(1078729200000)\/",
"ContractTermId":null,
"BillingDayOfMonth":0,
"PaymentScheduleFrequencyId":0,
"TotalPremium":200
}
};

Notice two things about System.Web.Helpers.Json.Encode's output:

  1. The property names are the .Net property names. The same code could not be used to post what should be the same model to MVC or to WebAPI.
  2. The EffectiveDate field has been converted to a Date function, enclosed in a string. Even if the Date function would reveal the correct value, the fact that it's in a string means JavaScript will not see it as a Date.

If I don't do anything with this object and just post it back to the MVC app, the resulting object does not have a valid date — all other values carry over, but the EffectiveDate property is 01/01/0001. So not only does it look odd, not only is it inconvenient in that JavaScript can't use it as-is (without picking apart the string), but it doesn't even work for round-tripping data to and from the client.

In doing some research on this topic, I came across Scott Hanselman's blog post describing the problem, and stating that the release of WebAPI won't have the issue since it will use JSON.Net (a.k.a. Newtonsoft.Json). Since I'm using the same model in an WebAPI call further downstream, I can verify that it does work as intended. It uses the JsonProperty decorators to rename the properties, and it serializes and deserializes like magic.

To solve this problem in MVC, you have to alter how it deals with JSON on the way out and on the way in.

On the way out is easy in my case, since I am manually spitting out JSON into the HTML. I just exchanged Json.Encode with Newtonsoft's serializer:

window.ScriptModel = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(new {
PaymentScheduleUrl = Url.Action("NewPaymentSchedule", "Contract"),
PaymentScheduleRequestModel = new PaymentScheduleRequestModel {
ContractTermId = Model.ContractTermId,
EffectiveDate = Model.StartDate ?? DateTime.Now,
TotalPremium = 200m
}
}));

And the browser sees:

window.ScriptModel={
"PaymentScheduleUrl":"/Contract/NewPaymentSchedule",
"PaymentScheduleRequestModel":{
"effDt":"2004-03-08T00:00:00",
"billDay":0,
"freq":0,
"prem":200
}
};

This is better. Of course, the controller action doesn't understand this. It's still looking for the .Net property names, and, since they don't exist on the incoming object, all values come back empty. (In this simple example, not only is EffectiveDate 01/01/0001, but TotalPremium is 0.0.)

The trick here is to override MVC's default model binder, so that it, too, uses the Newtonsoft.Json library. It is also consistent to have MVC use a value provider factory that also uses JSON.Net.

Fortunately, people smarter than I figured out these two steps. I found a value provider factory on this blog: http://www.dalsoft.co.uk/blog/index.php/2012/01/10/asp-net-mvc-3-improved-jsonvalueproviderfactory-using-json-net/
and the important piece, the model binder, that will translate the JSON property names to their real .Net names, is detailed here: http://stackoverflow.com/questions/4164114/posting-json-data-to-asp-net-mvc

My implementation looks like this:

And this code gets called from Application_Start (I actually added it to my WebApiConfig class (which, for some reason, exists in my MVC app even though it's obviously not the same as WebAPI), since other configuration-type things were being done here):

ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault());
ValueProviderFactories.Factories.Add(new JsonDotNetValueProviderFactory());

ModelBinders.Binders.DefaultBinder = new JsonDotNetDefaultModelBinder();

All this because, although Microsoft updated one of their web interfaces (WebAPI) to use the JSON.Net library that works, another one of their interfaces (MVC) uses their own, broken, JSON serialization library.