views:

477

answers:

3

I'm working with MVC recently and I've encountered a strange problem while trying to send request to my controller using ajax. I'm using JQuery (version 1.3.2) that came directly with MVC, I'm trying to send such ajax request:

$.post("Home/OpenTrade", { price: 1.5 }, function() { }, "json");

I've also tried parseFloat("1.5") instead of 1.5.
When I try to receive this value in controller using

[AcceptVerbs( HttpVerbs.Post)]
public void OpenTrade(float? price)

My price is always null. If I omit ? the controller is not called at all (which is nothing surprising), I've tried using decimal as well as double type. Furthermore, this function works when I'm sending integer data (if I send 1 this controller is called, and float? price is filled properly). Am I missing something, or is it a bug?

Ad. I can receive price as string, and then parse it manually, but I don't like this solution, as it's not elegant and it fights the whole purpose of using framework like MVC to do this for me.

Edit & Answer: Using Joel's advice, I've created a Model Binder, which I'll post, maybe someone will use it:


class DoubleModelBinder : IModelBinder
{
    #region IModelBinder Members

    public object BindModel(ControllerContext controllerContext, ModelBindingContext    bindingContext)
    {
        string numStr = bindingContext.ValueProvider[bindingContext.ModelName].AttemptedValue;
        double res;

        if (!double.TryParse(numStr, System.Globalization.NumberStyles.Number, System.Globalization.CultureInfo.InvariantCulture, out res))
        {
            if (bindingContext.ModelType == typeof(double?))
                return null;
            throw new ArgumentException();
        }

        if (bindingContext.ModelType == typeof(double?))
            return new Nullable<double>(res);
        else
            return res;
    }

    #endregion
}

It may be registered as double and double? binder, for double? it will pass null to controller, if value could not have been resolved.

Btw. Any ideas why floats and doubles don't work out of the box (for me?)?

Edit2 & Solution: Ok, this is going to be funny :). It didn't work for me, because requested string was sending 1.5432 (an example value), which is perfectly ok, but... MVC was trying to decode it internally using my culture settings, which are expecting numbers to be in format 1,5432, so the conversion has failed silently.
So, thing to remember: if you are living in strange country, double-check your culture settings.

+3  A: 

make a float model binder. That can pull the appropriate value from the form collection, parse it, and return it as the argument

Joel Martinez
A: 

EDIT: Do you need to be using jQuery post? Is there any way you can use the built in support for ajax to create a link and what is the result in that case? e.g.

Ajax.ActionLink("Link Name", "OpenTrade", "Home",
                   new { price = 1.5f },
                   new AjaxOptions
                   {
                       OnSuccess = "success",
                       ....
                   })

When specifying a float value you generally have to postfix the value with 'f' e.g.

float f = 1.5f;

Have you tried this?

An alternative solution would be to change your service method to:

[AcceptVerbs( HttpVerbs.Post)]
public void OpenTrade(int dollars, int cents)
Simon Fox
Ad 1. Remember, that I have number inside javascript, not inside c# code, so adding 'f' wouldn't help. Ad 2. It is a solution, but it's even less elegant than getting string imho (I'm ignoring the fact, that I'm passing money value as float number, which is almost never a good idea, but in this case, I know what I'm doing)
Ravadre
Ad edit. I rather need whole logic implemented in JS, as I'm not just putting few links with ajax queries, besides, I don't believe that problem lies on JS side, which is just passing data to MVC in a given format.
Ravadre
Ad 1. Of course, silly me :)
Simon Fox
A: 

Have you checked to see what the JSON response from the server is? I notice you haven't encapsulated your price variable with double quotes, so your post to the server will look like:

{'price':1.5}

I don't know if that will be a problem with only one data parameter, but I suspect what you actually want it to look like is

"{'price':1.5}"

jQuery ajax methods being passed to ASP.Net methods should have a string for the data parameter otherwise jQuery may serialise the data incorrectly. Having the string means jQuery will leave your JSON object alone and pass the entire string to ASP.NET for parsing on the server side.

Phil.Wheeler
I don't think this is the case, when I've did what you have advised me, everything has stopped working :), like if I've tried to pass some other data, which are string - they weren't deserialized by mvc at all.
Ravadre