青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

huangyi5209

  C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
  0 Posts :: 13 Stories :: 0 Comments :: 0 Trackbacks

常用鏈接

留言簿

我參與的團隊

搜索

  •  

最新評論

Sunday, October 10, 2010

Passing a JSON array to a WCF service

While the following information is available on the Internet, I had to piece it together from various sources, so for my own documentation and hopefully to help someone else, here is a simple (I hope) example of passing a JSON array to a WCF service, all in one place. It can be easily generalized to passing any JSON-serialized object to WCF, but that is better documented than arrays.

Note: This sample uses jQuery and Douglas Crockford’s JSON2. It also uses some features of HTML 5, including placeholder text, autofocus fields and offline storage, but these aren’t essential for the solution.

First, let’s look at the HTML, because it’s probably the simplest part of the solution:

index.html

<!DOCTYPE html>

<html>

<head>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <link rel="stylesheet" href="styles/branding.css" />

    <title>Send Array to WCF Service</title>

</head>

<body>

    <div id="content">

        <h3>User</h3>

        <form id="demographics_form">

            <span>Last Name: </span>

            <input id="last_name" name="last_name" type="text" placeholder="Last name" autofocus required />

            <br />

            <span>First Name: </span>

            <input id="first_name" name="first_name" type="text" placeholder="First name" />

            <br />

            <span>Email: </span>

            <input id="email_address" name="email_address" type="email" placeholder="someone@somewhere.com" />

            <br />

            <input id="save_button" type="button" value="Save" />

        </form>

    </div>

    <p id="app_status">

    </p>

    <script src="scripts/json2.js" type="text/ecmascript"></script>

    <script src="scripts/jquery-1.4.2.min.js" type="text/ecmascript"></script>

    <script src="scripts/main.js" type="text/ecmascript"></script>

</body>

</html>

Pretty much a simple form with three fields and a button. Pay attention to the input elements name attributes – we will be using those in various places. Note that the form doesn’t have action or method attributes. We will assign an event handler to the button in a bit. There is also a p element with an id of app_status which will be used to display status messages.

With that out of the way, let’s look at the JavaScript:

main.js

var UserApp = {

    docReady: function () {

        UserApp.loadForm();

        $("#save_button").bind("click", UserApp.sendFormData);

    },

 

    // Load form from saved data. Presumes that each input element's id is the same as its name.

    loadForm: function () {

        var formDataString = localStorage.getItem("user_data");

 

        if (formDataString) {

            var formData = JSON.parse(formDataString);

 

            for (var i in formData) {

                var fieldId = "#" + formData[i].name;

                $(fieldId).val(formData[i].value);

            }

        }

    },

 

    // Save data from a form. Presumes there is only one form element on a page.

    saveFormData: function () {

        var formData = $("form").serializeArray();

 

        localStorage.setItem("user_data", JSON.stringify(formData));

        return { nvps: formData };

    },

 

    sendFormData: function () {

        var formData = UserApp.saveFormData();

        $.ajax({

            type: "POST",

            url: "MyProject/UserSvc.svc/SaveUserData",

            data: JSON.stringify(formData),

            contentType: "application/json; charset=utf-8",

            dataType: "json",

            success: function (data) {

                if (data && data.d && data.d.Message) {

                    $("#app_status").html(data.d.Message);

                }

            },

            error: function (req, status, error) {

                if (req && req.responseText) {

                    var ex = JSON.parse(req.responseText);

 

                    if (ex && ex.Message) {

                        $("#app_status").html(ex.Message);

                    }

                    else {

                        $("#app_status").html("An error occurred saving the loan application data.");

                    }

                }

            }

        });

    }

};

 

$(document).ready(UserApp.docReady);

On the document becoming ready we execute the docReady function. It calls the loadForm function which loads the form values from local storage (if they exist), and also attaches the sendFormData function as the event handler for the “Save” button. We are storing the data in local storage using “user_data” as a key and a JSON-serialized array for the form elements (we will see how we create that array in the SaveFormData function). After parsing the JSON array we iterate over it to fill in the form input fields.

The saveFormData function is the opposite of the loadForm function in that it serializes the form’s input values using jQuery’s serializeArray function, which is one of the reasons I chose this approach. It does one other thing, which is to wrap the (unserialized) array in an object with a single member, nvps (which stands for “name-value pairs”), that holds the array, and returns this object. Again, we’ll see why later. To be clear, we are changing the bare array, which WCF will not accept as a method parameter:

[ { name: “last_name”, value: “Smith”}, {name: “first_name”, value: “John”}, {name: “email_address”, value: “john.smith@xyz.com”} ]

…to a wrapped object, which WCF will take:

{ nvps:  [ { name: “last_name”, value: “Smith”}, {name: “first_name”, value: “John”}, {name: “email_address”, value: “john.smith@xyz.com”} ] }

Finally there is the sendFormData function, the event handler for the “Save” button. It consists of a single AJAX call to the WCF service, sending up the JSON-serialized wrapped object as the sole parameter for the SaveUserData method, and setting the status on the HTML page based on the success or failure of that call. Two things to note about that. First, on success the data coming down (a simple object with a single public property in it called Message) will be wrapped within a JavaScript object called data in a member called d. So any access to data returned on success is via data.d.xyz, in our case data.d.Message. This use of data.d as a (successful) response wrapper appears to be hold for all JSON-enabled WCF services.

Second, if there was a server-side exception it will come down to the error callback as the JSON-serialized responseText member of the (XMLHttpRequest) request parameter. After parsing the JSON you can get to various exception members, although in our case we are just interested in the exception’s Message member. When debugging both success and failures it is very helpful to use Fiddler or similar tools to see what is getting passed back and forth with each HTTP request and response.

Now it’s time to see the server-side implementation. Let’s look at the WCF interface definition first:

IUserSvc.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.ServiceModel.Web;

using System.Text;

 

namespace MyProject

{

    [ServiceContract]

    public interface IUserSvc

    {

        [OperationContract]

        [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json)]

        ResultMessage SaveUserData(NameValuePairs nvps);

    }

 

    [DataContract]

    public class NameValuePair

    {

        [DataMember]

        public string name { get; set; }

        [DataMember]

        public string value { get; set; }

    }

 

    [DataContract]

    public class ResultMessage

    {

        [DataMember]

        public string Message { get; set; }

    }

 

    [CollectionDataContract(Namespace = "")]

    public class NameValuePairs : List<NameValuePair>

    {

    }

}

The interface is pretty simple. There is a single SaveUserData method which takes in a collection of name-value pairs and returns a simple object that holds a result message. There are three things to notice here, and all are important. The first are the declarative attributes decorating the method. The following is where the real wiring for receiving and responding in JSON happens:

[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json)]

The Method can be either POST or GET (as long as your JavaScript code sends the request in the appropriate format). The BodyStyle and ResponseFormat parameters are required to get JSON in and out of the method. Any attempt to use a different BodyStyle (such as WebMessageBodyStyle.Bare) will result in a run-time exception because of settings in the web.config file, which we’ll see later.

Second, the parameter name to the method is nvps. Note this is the same name as the single member returned in the wrapper object on the array of form input field values in the JavaScript saveFormData function. This is some of the “magic” you just have to trust, but as far as I can tell, the parameter name to the WCF method must match the member name in the JavaScript wrapper object. In other words, it appears that when dealing with JSON, WCF is using name-matching between the JSON-serialized names and names in the managed code, probably via reflection.

Finally, while you don’t see it explicitly in the JavaScript code above, the jQuery serializeArray function returns an array of objects, one object for each input element in the form. Each object in the array contains two members - name, whose value matches the name attribute on the input element, and value, which contains the actual field’s value. Note that the NameValuePair class in the interface also uses name and value as member names. Again, these must match (as far as I can tell) the JavaScript member names to make all this work.

Here is the WCF implementation:

UserSvc.svc.cs

using System;

using System.Collections.Generic;

using System.Data;

using System.Data.SqlClient;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.ServiceModel.Activation;

using System.ServiceModel.Web;

using System.Text;

 

namespace MyProject

{

    [AspNetCompatibilityRequirements (RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

    public class UserSvc : IUserSvc

    {

        public ResultMessage SaveUserData(NameValuePairs nvps)

        {

            var columns = new StringBuilder();

            var parameters = new StringBuilder();

            var rm = new ResultMessage() { Message = "User saved successfully." };

 

            using (var conn = new SqlConnection(Properties.Settings.Default.AppDb))

            using (var cmd = new SqlCommand() { CommandType = CommandType.Text, Connection = conn })

            {

                var paramCollection = cmd.Parameters;

                var rows = 0;

 

                try

                {

                    if (nvps == null || nvps.Count == 0)

                    {

                        throw new ArgumentNullException("nvps");

                    }

 

                    foreach (NameValuePair nvp in nvps)

                    {

                        columns.Append(nvp.name).Append(",");

                        parameters.Append("@").Append(nvp.name).Append(",");

                        paramCollection.Add(new SqlParameter("@" + nvp.name, nvp.value));

                    }

 

                    // KLUDGE: Remove trailing commas.

                    columns.Remove(columns.Length - 1, 1);

                    parameters.Remove(parameters.Length - 1, 1);

                    cmd.CommandText = String.Format(Properties.Settings.Default.InsertSql, columns.ToString(), parameters.ToString());

                    conn.Open();

                    rows = cmd.ExecuteNonQuery();

                    rm.Message = String.Format(Properties.Settings.Default.SuccessMessage, rows, cmd.CommandText);

                }

                catch (Exception ex)

                {

                    rm.Message = ex.Message;

                }

            }

 

            return rm;

        }

    }

}

There isn’t really much going on here. As noted, the method parameter nvps must match the member within the JSON-serialized wrapper object around the array being sent to the method. As the code iterates through the array (collection), note also the use of name and value, again, matching the object member namess that are within the array. The code basically builds a dynamic, parameterized SQL INSERT statement (see the web.config) that assumes the underlying table column names are the same as the input elements name attributes. Cheesy, I know, but it shows we’re actually “doing something” on the server. I don’t claim this to be production-quality! The interesting thing about the code as written, however, is that by simply changing the form to add more input elements and altering the table to add more columns, additional data could be accommodated with no change in the JavaScript or managed code, which gives a bit of flexibility that I like.

Finally, we have the web.config file:

web.config

<?xml version="1.0"?>

<configuration> 

  <configSections>

    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >

      <section name="LoanAppDataRouter.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />

    </sectionGroup>

  </configSections>

  <system.web>

    <compilation debug="true" targetFramework="4.0" />

  </system.web>

  <system.serviceModel>

    <bindings>

      <webHttpBinding>

        <binding name="MyBinding">

          <security mode="TransportCredentialOnly">

            <transport clientCredentialType="Windows"/>

          </security>

        </binding>

      </webHttpBinding>

    </bindings>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />

    <services>

      <service name="MyProject.UserSvc" behaviorConfiguration="JsonBehavior">

        <endpoint address="" binding="webHttpBinding" bindingConfiguration="MyBinding" behaviorConfiguration="JsonBehavior" contract="MyProject.IUserSvc">

          <identity>

            <dns value="mywebserver"/>

          </identity>

        </endpoint>

      </service>

    </services>

    <behaviors>

      <endpointBehaviors>

        <behavior name="JsonBehavior">

          <enableWebScript/>

        </behavior>

      </endpointBehaviors>

      <serviceBehaviors>

        <behavior name="JsonBehavior">

          <serviceMetadata httpGetEnabled="true"/>

          <serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

<system.webServer>

    <modules runAllManagedModulesForAllRequests="true"/>

  </system.webServer>

<applicationSettings>

  <MyProject.Properties.Settings>

   <setting name="InsertSql" serializeAs="String">

    <value>INSERT INTO Users ({0}) VALUES({1})</value>

   </setting>

   <setting name="AppDb" serializeAs="String">

    <value>server=.;initial catalog=ApplicationDB;integrated security=sspi;</value>

   </setting>

   <setting name="SuccessMessage" serializeAs="String">

    <value>Inserted {0} rows using the following statement: {1}</value>

   </setting>

  </MyProject.Properties.Settings>

</applicationSettings>

</configuration>

I won’t go over all of this in detail, but simply call out the pieces that make the JSON work with WCF. You can also see the three properties being stored for access by the managed code at the end of the file. The important part is contained in the service element. Note first the binding attribute of the endpoint element is set to webHttpBinding. This is required for JSON to work. The endpoint also points via the behaviorConfiguration attribute to “JsonBehavior.” If you look at the “JsonBehavior” behavior element under endpointBehaviors, you will see an empty enableWebScript element. This is also required for JSON.

The serviceBehaviors element is basically set up to ease debugging. It enables GET requests (so you could do a URL-encoded request if you chose, even from a browser’s address bar) as well as turning on some debugging sugar. You won’t want that to go into production, however. The rest of the web.config is fairly self-evident. I’ve called out the things you need to pay attention to specifically for WCF services to interact with a JSON client, which could be JavaScript, or anything else that eats and excretes JSON (the list of which is fairly large).

Hopefully this post will help save someone some time by pulling all the required pieces into one place and calling out some of the more obscure aspects of JSON-to-WCF interaction. As always, I appreciate comments, corrections and questions.



http://ednortonengineeringsociety.blogspot.com/2010/10/passing-json-array-to-wcf-service.html
posted on 2011-04-21 22:14 huangyi5209 閱讀(1307) 評論(0)  編輯 收藏 引用 所屬分類: JavascriptC#

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久精品国产99精品国产亚洲性色| 浪潮色综合久久天堂| 久久久亚洲国产天美传媒修理工| 亚洲欧洲三级| 亚洲国产精品成人| 久久午夜av| 亚洲欧美日韩在线一区| 亚洲国产合集| 欧美激情一区二区三区蜜桃视频| 久久国产精品99久久久久久老狼| 午夜免费日韩视频| 欧美一区二区在线| 香蕉乱码成人久久天堂爱免费| 亚洲视频免费看| 久久av在线| 老司机精品福利视频| 免费欧美在线视频| 日韩一级在线观看| 亚洲欧美日韩爽爽影院| 欧美一区二区国产| 亚洲色诱最新| 美乳少妇欧美精品| 裸体歌舞表演一区二区| 老司机午夜精品视频在线观看| 欧美伦理在线观看| 国产精品久线观看视频| 国产婷婷成人久久av免费高清| 国产免费成人av| 国产精品一区二区久激情瑜伽| 欧美国产激情| 欧美日韩国产一区二区三区地区| 国产日韩欧美视频| 黄色欧美日韩| 日韩亚洲精品在线| 日韩视频免费观看| 亚洲午夜激情| 久久精品夜色噜噜亚洲a∨| 中国av一区| 欧美阿v一级看视频| 亚洲精品欧美激情| 午夜久久资源| 欧美日韩一区综合| 黑人操亚洲美女惩罚| 日韩一级二级三级| 欧美阿v一级看视频| 一区二区三区国产在线| 欧美在线视频一区二区三区| 制服诱惑一区二区| 美玉足脚交一区二区三区图片| 午夜精品成人在线| 亚洲激情图片小说视频| 亚洲性人人天天夜夜摸| 久久久久久亚洲精品杨幂换脸| 国产精品你懂得| 99一区二区| 毛片基地黄久久久久久天堂| 性欧美video另类hd性玩具| 欧美国产日韩xxxxx| 亚洲成色777777女色窝| 精品动漫一区| 噜噜爱69成人精品| 亚洲综合国产| 欧美激情亚洲精品| 日韩一级黄色大片| 欧美夫妇交换俱乐部在线观看| 亚洲免费影院| 国产精品一区二区在线观看网站 | 亚洲欧洲日韩在线| 久久精品二区亚洲w码| 黄色成人精品网站| 性欧美激情精品| 99视频精品免费观看| 久久精品国产99国产精品澳门| 激情五月综合色婷婷一区二区| 久久丁香综合五月国产三级网站| 在线一区免费观看| 国产精品推荐精品| 一区二区在线视频| 牛夜精品久久久久久久99黑人| 亚洲欧美影院| 亚洲国产精品成人精品| 亚洲大胆人体视频| 亚洲一级二级在线| 欧美视频一区二区三区| 国产亚洲精久久久久久| 久久久av毛片精品| 亚洲女女女同性video| 欧美三级第一页| 欧美在线高清| 亚洲欧美日韩视频二区| 国产欧美精品在线| 欧美日韩亚洲免费| 亚洲欧美日韩一区二区三区在线观看 | 亚洲影院在线| 国产精品丝袜xxxxxxx| 亚洲欧美日韩天堂| 午夜一区二区三视频在线观看| 韩国女主播一区二区三区| 麻豆av一区二区三区| 葵司免费一区二区三区四区五区| 尤物yw午夜国产精品视频| 亚洲欧洲精品一区二区三区| 欧美视频中文字幕| 午夜欧美理论片| 久久激情视频久久| 亚洲婷婷综合久久一本伊一区| 亚洲一卡久久| 极品少妇一区二区| 亚洲七七久久综合桃花剧情介绍| 久久久噜噜噜久久中文字幕色伊伊| 久久精品一二三区| 亚洲激情偷拍| 一本色道久久88亚洲综合88| 在线播放豆国产99亚洲| 欧美国产综合| 国产精品实拍| 亚洲欧美日韩高清| 久久久精品性| 欧美在线免费播放| 快播亚洲色图| 一本色道久久88综合日韩精品| 欧美中文字幕视频| 一区二区日本视频| 欧美一区二区三区在线观看视频| 亚洲人成网站777色婷婷| 日韩一级不卡| 亚洲每日在线| 久久成人av少妇免费| 亚洲三级影院| 久久久蜜臀国产一区二区| 99re热精品| 国内精品久久久久影院色| 亚洲人成啪啪网站| 久久中文在线| 欧美一区影院| 欧美手机在线视频| 亚洲风情在线资源站| 国产午夜精品在线| 亚洲欧美在线看| 亚洲女同同性videoxma| 欧美精品免费在线观看| 亚洲精品一区二区三区樱花 | 伊人天天综合| 亚洲一区免费网站| 在线亚洲一区观看| 美女尤物久久精品| 免费在线观看日韩欧美| 国产欧美亚洲日本| 亚洲特级毛片| 亚洲一区免费网站| 欧美日韩国产在线看| 男女精品网站| 亚洲电影免费观看高清完整版在线观看| 亚洲制服丝袜在线| 久久精品国产2020观看福利| 国产麻豆综合| 欧美一区二区三区在| 久久亚洲美女| 亚洲人成网站777色婷婷| 欧美激情一区二区久久久| 亚洲国产精品传媒在线观看| 99国产精品视频免费观看一公开 | 亚洲国产乱码最新视频| 在线观看视频日韩| 久久国产一区二区| 欧美激情女人20p| 一区二区三区在线免费视频| 久久久久高清| 亚洲另类在线视频| 国产精品国产三级国产普通话99| 午夜亚洲伦理| 国户精品久久久久久久久久久不卡| 老司机午夜免费精品视频| 一区二区三区产品免费精品久久75| 欧美综合国产| 亚洲国产专区| 欧美性色视频在线| 久久人人爽国产| 亚洲国内自拍| 久久精品国产欧美激情| 亚洲日本免费| 国产精品中文字幕欧美| 欧美jizzhd精品欧美巨大免费| 日韩一级黄色av| 快射av在线播放一区| 亚洲一区中文字幕在线观看| 亚洲国产成人在线播放| 午夜亚洲福利| 亚洲精品色图| 蜜臀av性久久久久蜜臀aⅴ四虎| 91久久久亚洲精品| 国产一区二区日韩| 欧美大胆成人| 亚洲制服少妇| 亚洲精选一区二区| 在线视频欧美精品| 久久精品国产99国产精品澳门| 美女网站在线免费欧美精品| 亚洲男人第一av网站| 国产亚洲成人一区|