MVC3模型DisplayFormat和JSON

时间:2012-03-02 17:42:32

标签: .net asp.net-mvc asp.net-mvc-3

我有一个模型,它有一些双重属性,并带有一个DisplayFormat,它将double转换为一个很好的可读百分比..例如

[DisplayFormat(DataFormatString = "{0:P2}")]
public Nullable<double> Yearly_act_pct { get; set; }

这在HTML部分中很好用,我在

中包装了调用
@Html.DisplayFor(modelItem => item.Yearly_act_pct)

但是,当我将其中一些对象转储到JSON提要中时,DisplayFormats似乎被忽略了,所以我最终得到了原始小数,而且往往是大小数。

我该如何制作

return Json(myObjects, JsonRequestBehavior.AllowGet);

尊重DisplayFormats?

3 个答案:

答案 0 :(得分:2)

return Json(myObjects, JsonRequestBehavior.AllowGet)的调用实际上会返回JsonResultJsonResult的内部执行呼叫:

JavaScriptSerializer serializer = new JavaScriptSerializer();
response.Write(serializer.Serialize(Data));

如果你查看JavascriptSerializer的MSDN,你会有一个简单的转换。此实现似乎不尊重DisplayFormat。

您可以编写一个派生自JsonResult的类,以尊重DisplayFormat属性。

答案 1 :(得分:1)

DataAnnotations命名空间属性仅处理动态数据控件和显示格式。在将对象传递给Json()方法之前,您需要做的只是一些基本的舍入。这样的东西就足够了:

myObjects.Yearly_act_pct = Math.Round(myObjects.Yearly_act_pct, 2); // provided you wanted to round to nearest two fractional digits
return Json(myObjects, JsonRequestBehavior.AllowGet);

这会为您提供“小双倍”值,但您仍然传递double,而不是string,可以是格式化double。不确定这是否有意义,但doubledouble,你可以做的最好是将其舍入,以便它没有超出的小数位数。

答案 2 :(得分:1)

人们在使用Serialization时需要自定义输出格式时使用的一种解决方法是创建字符串属性:

    [DataMember(Name = "price", Order = 23)]
    [XmlElement("price", Order = 23)]
    public string Price_String
    {
        get
        {
            return Formatter.FormatAsCurrency(this.Price);
        }
        set
        {
            this.Price = Formatter.ParseCurrency(value);
        }
    }

    [XmlIgnore]
    public decimal Price { get; set; }

Formatter是我自己的一个自定义类,它可以解析特定类型的格式。这些不相关,但我会将它们包括在内:

    public static string FormatAsCurrency(decimal? amount)
    {
        return amount.HasValue ? String.Format("{0:C}USD", amount).Replace("$","") : null;
    }
    public static decimal ParseCurrency(string value)
    {
        return !String.IsNullOrEmpty(value) ? decimal.Parse(value.Replace("USD", "")) : 0;
    }
    public static decimal? ParseNullableCurrency(string value)
    {
        return !String.IsNullOrEmpty(value) ? decimal.Parse(value.Replace("USD", "")) as decimal? : null;
    }

在我的示例中,我已经为DataContract和Xml序列化标记了我的属性。这不是理想的,但当时是唯一的解决方法。

我还在我的控制器中创建了一个方法来返回响应“

    public ContentResult GetContentResult(object responseObject)
    {
        #region Output Format
        if (this.ResponseFormat == ResponseFormatEnum.JSON)
        {
            string json = "";

            try
            {
                System.Runtime.Serialization.Json.DataContractJsonSerializer jsonserializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(responseObject.GetType());
                MemoryStream ms = new MemoryStream();
                jsonserializer.WriteObject(ms, responseObject);
                json = Encoding.Default.GetString(ms.ToArray());
                ms.Close();
                ms.Dispose();
                jsonserializer = null;
            }
            catch(System.Exception ex)
            {
                string err = ex.Message;
            }

            return new ContentResult() { Content = json, ContentType = "application/json" };

        }
        else
        {
            string xml = "";
            try
            {
                MemoryStream ms = new MemoryStream();
                System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(responseObject.GetType());
                System.Xml.Serialization.XmlSerializerNamespaces ns = new System.Xml.Serialization.XmlSerializerNamespaces();
                ns.Add("", "");
                ms = new MemoryStream();
                serializer.Serialize(ms, responseObject, ns);
                xml = Encoding.Default.GetString(ms.ToArray()); ms.Close();
                ms.Dispose();
                serializer = null;
            }
            catch (System.Exception ex)
            {
                throw ex;
            }

            return new ContentResult() { Content = xml, ContentType = "text/xml" };
        }
        #endregion
    }

使用它:

    public ActionResult Feed()
    {
        ViewModels.API.Deals.Response response = new ViewModels.API.Deals.Get();
        return GetContentResult(response);            
    }

我的示例比您使用的示例复杂一点,但它的工作原理(包括XML和JSON)