使用json传递窗口小部件数据并保存到数据库

时间:2014-12-15 16:21:47

标签: c# jquery asp.net sql-server json

我刚刚再次回到这个要求,因为当时我被迫离开它以做更重要的要求。

我问了一个类似的问题here,答案有所帮助。但是,在那个问题中,我传递了测试数据并将其保存到数据库中。但是,我无法弄清楚如何保存实际的小部件信息。该链接帮助我成功传递了json。

我在尝试保存数据时收到此消息。 enter image description here

  

的jQuery

    function updateWidgetData() {
        var items = [];
        $('.column').each(function () {
            var columnId = $(this).attr('id');
            $('.dragbox', this).each(function (i) {
                var collapsed = 0;
                if ($(this).find('.dragbox-content').css('display') == "none")
                    collapsed = 1;
                //Create Item object for current panel  
                var item = {
                    id: $(this).attr('id'),
                    collapsed: collapsed,
                    order: i,
                    column: columnId
                };
                //Push item object into items array  
                items.push(item);
            });
        });
        //Assign items array to sortorder JSON variable  
        var sortorder = { items: items };

        $.ajax({
            url: "/Handlers/SaveWidgets.ashx",
            type: "POST",
            contentType: "application/json; charset=uft-8",
            dataType: "json",
            data: JSON.stringify(sortorder),
            success: function (response) {
                alert("Passed json");
            },
            error: function (error) {
                alert("Failed passing json.");
            }
        });
  

处理程序

   public void ProcessRequest(HttpContext context)
    {
        String json = String.Empty;
        // you have sent JSON to the server
        // read it into a string via the input stream
        using (StreamReader rd = new StreamReader(context.Request.InputStream))
        {
            json = rd.ReadToEnd();
        }

        // create an instance of YourDataModel from the
        // json sent to this handler
        SaveWidgetsDAL data = null;
        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(SaveWidgetsDAL));
        using (MemoryStream ms = new MemoryStream())
        {
            byte[] utf8Bytes = Encoding.UTF8.GetBytes(json);
            ms.Write(utf8Bytes, 0, utf8Bytes.Length);
            ms.Position = 0;
            data = serializer.ReadObject(ms) as SaveWidgetsDAL;
        }
        // update the DB and
        // send back a JSON response
        int rowsUpdated = 0;

        foreach (var item in data.wdata)
        {
            using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["dboCao"].ConnectionString))
            {
                conn.Open();

                using (SqlCommand cmd = new SqlCommand("UPDATE tWidgetControl SET SortNo = @SortNo, ColumnId = @ColumnId, Collapsed = @Collapsed "
                    + "WHERE UserId = @UserId AND WidgetId = @WidgetId;", conn))
                {
                    cmd.Parameters.AddWithValue("@SortNo", item.SortNo);
                    cmd.Parameters.AddWithValue("@ColumnId", item.ColumnId);
                    cmd.Parameters.AddWithValue("@Collapsed", item.Collapsed);
                    cmd.Parameters.AddWithValue("@UserId", "2");
                    cmd.Parameters.AddWithValue("@WidgetId", item.WidgetId);
                    rowsUpdated = cmd.ExecuteNonQuery();
                }
                conn.Close();
            }
        }

        context.Response.ContentType = "application/json";
        context.Response.Write("{ \"rows_updated\": " + rowsUpdated + " }");
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
  

小部件数据类

public class SaveWidgetsDAL
{
    public List<Widgets> wdata { get; set; }

    public SaveWidgetsDAL() { }

    public class Widgets
    {
        [DataMember]
        public string SortNo { get; set; }

        [DataMember]
        public string ColumnId { get; set; }

        [DataMember]
        public string Collapsed { get; set; }

        [DataMember]
        public string Title { get; set; }

        [DataMember]
        public string UserId { get; set; }

        [DataMember]
        public string WidgetId { get; set; }
    }
}

我想我需要将json保存到列表中,然后将每个窗口小部件信息插入/更新到数据库中。但是,当我尝试这个时,我收到上面的错误。我显然遗漏了一些东西,但我不确定它是什么。我的处理程序中发生此错误,但SaveWidgetsDAL中的列表为空,从而导致NullReference。我不确定我错过了什么或确定从哪里开始。非常感谢任何帮助!

编辑1:

我已经将我的数据库与SaveWidgetsDAL一起更改了一段时间。

  

SaveWidgetsDAL

[DataContract]
public class SaveWidgetsDAL
{
    [DataMember(Name = "items")]
    public List<Widgets> wdata { get; set; }

    public SaveWidgetsDAL() { }

    public class Widgets
    {
        [DataMember(Name = "order")]
        public string SortNo { get; set; }

        [DataMember(Name = "column")]
        public string ColumnId { get; set; }

        [DataMember(Name = "collapsed")]
        public string Collapsed { get; set; }

        [DataMember(Name = "id")]
        public string Title { get; set; }
    }
}
  

Handler(只是foreach)

foreach (var item in data.wdata)
{
    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["dboCao"].ConnectionString))
    {
        conn.Open();

        using (SqlCommand cmd = new SqlCommand("UPDATE tWidgetTest SET Title = @Title, SortNo = @SortNo, ColumnId = @ColumnId, Collapsed = @Collapsed "
                    + "WHERE UserId = @UserId AND Title = @Title;", conn))
         {
             cmd.Parameters.AddWithValue("@Title", item.Title);
             cmd.Parameters.AddWithValue("@SortNo", item.SortNo);
             cmd.Parameters.AddWithValue("@ColumnId", item.ColumnId);
             cmd.Parameters.AddWithValue("@Collapsed", item.Collapsed);
             cmd.Parameters.AddWithValue("@UserId", "2");
             rowsUpdated = cmd.ExecuteNonQuery();
          }
         conn.Close();
     }
 }

但是,我现在在插入数据库时​​遇到此错误。 enter image description here

我能够看到我的foreach计数是11,但是Collapsed,SortNo,ColumnId,Title对于每个项目都是null。

1 个答案:

答案 0 :(得分:1)

问题似乎是c#数据协定中指定的data member names与您生成的JSON中的JSON属性名称不匹配。您的JavaScript代码生成的JSON看起来像

{"items":[{"id":"1","collapsed":"False","order":"1","column":"1"}]}

但是这些属性名称不是c#类中的属性名称,并且您没有覆盖这些名称。请尝试以下内容:

[DataContract]
public class SaveWidgetsDAL
{
    [DataMember(Name="items")]
    public List<Widgets> wdata { get; set; }

    public SaveWidgetsDAL() { }

    [DataContract]
    public class Widgets
    {
        // I was able to figure out which JSON properties to which to map these properties.
        [DataMember(Name = "column")]
        public string ColumnId { get; set; }

        [DataMember(Name = "collapsed")]
        public string Collapsed { get; set; }


        // However it is unclear how to map these to your JSON.  
        [DataMember(Name = "sortno")]
        public string SortNo { get; set; }

        [DataMember(Name = "title")]
        public string Title { get; set; }

        [DataMember(Name = "userid")]
        public string UserId { get; set; }

        [DataMember(Name = "widgetid")]
        public string WidgetId { get; set; }
    }
}

我能够为collapsed: collapsedcolumn: columnId推断出正确的c#数据成员名称,但我无法弄清楚如何映射其余的,因为它们似乎不匹配1-1 。您需要进一步修复data member names以使其完全匹配。

<强> UPDATE2

在更新的问题中,您省略了嵌套[DataContract]类的Widgets属性:

    // [DataContract] missing
    public class Widgets
    {

您需要确保外部类和嵌套类都具有此属性。

<强>更新

这是创建JSON的代码的一部分:

            var collapsed = 0;
            if ($(this).find('.dragbox-content').css('display') == "none")
                collapsed = 1;
            //Create Item object for current panel  
            var item = {
                id: $(this).attr('id'),
                collapsed: collapsed,
                order: i,
                column: columnId
            };
            //Push item object into items array  
            items.push(item);

        var json = JSON.stringify(sortorder);

因此,item数组中的每个object items只包含这四个命名属性:

  • id
  • collapsed
  • order
  • column

您在var item = { id: value1, collapsed: value2, ...};语句中使用的属性名称是JSON.stringify()写入json字符串的名称。 c#code 中指定的数据成员名称必须与这些名称完全匹配,才能使用DataContractJsonSerializer对其进行反序列化。因此,以下c#类将反序列化这四个命名属性:

[DataContract]
public class SaveWidgetsDAL
{
    [DataMember(Name = "items")]
    public List<Widgets> wdata { get; set; }

    public SaveWidgetsDAL() { }

    [DataContract]
    public class Widgets
    {
        // I was able to figure out which JSON properties to which to map these properties.
        [DataMember(Name = "id")]
        public string Id { get; set; }

        [DataMember(Name = "collapsed")]
        public string Collapsed { get; set; }

        [DataMember(Name = "order")]
        public string Order { get; set; }

        [DataMember(Name = "column")]
        public string ColumnId { get; set; }
    }
}

如果您需要传输其他属性,则需要在var item语句中添加它们,然后在Widgets类中添加具有相同数据成员名称的属性。要确认您已正确匹配名称,可以使用Visual Studio调试ProcessRequest()方法,并通过以下方式手动检查json字符串或debug log json字符串:< / p>

    System.Diagnostics.Debug.WriteLine(json);

这将允许您查看JSON并确保您的数据成员名称与您的JSON属性名称匹配。