Silverlight与Asp.Net MVC 通讯

最近一周分配了个任务,编辑配置,需要做成web的。要求有拖拽、旋转、选择多边形范围⊙﹏⊙。

考虑到自己的烂jq,申请用SilverLight,居然可以用这个没娘的孩儿。

Silverlight需要与MVC主项目通讯,无外乎是Get、Post,别的没用到。

  1. 获取地址

    WebRequest创建时需要Uri,而且是绝对路径的,需要获取xap所在的地址。

    var scriptObject = HtmlPage.Window.GetProperty("location") as ScriptObject;
    var hostUrl = scriptObject.GetProperty("href").ToString();
    

    这样获取的就是xap所在的页面的地址,再加入控制器方法名即可创建WebRequest。

  2. Get

    参数传递需要拼接在请求里的Url里。

    var pstr = string.Join("&", parameters.Select(p => string.Format("{0}={1}", p.Name, p.Value)));
    uriStr += string.Format("/?{0}", pstr);

    创建好WebRequest后可设置属性Method为"GET"即可。

    然后就可以通过 request.BeginGetResponse的方法获取回应。

    如果需要从返回值里读出数据,则只需

    DataContractJsonSerializer ser = new DataContractJsonSerializer(returnType);
    object obj = ser.ReadObject(responseStream);
    

    obj即为解析完的数据。

  3. Post

    Post是创建WebRequest与Get相同,只不过参数不能放在Url里,而是提交表单的形式。传递多个参数需要使用boundary标记。

    request.ContentType = "multipart/form-data; boundary=---------------------------" + boundary;
    

    boundary为随机字符串,在一次Post中保持一致。

    具体boundary使用参考了Netsuite的博客

    参数需要序列化MVC才能解析,除非MVC使用别的解析方法。序列化时可写入临时的MemoryStream,设置Request的ContentLength为MemoryStream的长度后,再Copy给RequestStream

    public static void Post<TResult>(
      string controllerMethod,
      Action<TResult> responseCallback,
     params Parameter<object>[] parameters)
    {
        string boundary = GetBoundaryStr();
        HttpWebRequest request = GetRequest(controllerMethod, RequestMethod.Post);
        request.ContentType = "multipart/form-data; boundary=---------------------------" + boundary;
    
        MemoryStream ms = new MemoryStream();
        foreach (var item in parameters)
        {
            var parameter = item.Value;
            byte[] data = null;
            if (parameter is string)
            {
                data = SerializeStrParameter(boundary, item.Name, (string)parameter);
            }
            else if (parameter is byte[])
            {
                data = SerializeBinParameter(boundary, item.Name, (byte[])parameter);
            }
            else if (parameter is object)
            {
                data = SerializeObjectParameter(boundary, parameter, item.Name);
            }
            if (data != null)
            {
                ms.Write(data, 0, data.Length);
            }
        }
        var endData = Encoding.UTF8.GetBytes("-----------------------------" + boundary + "--");
        ms.Write(endData, 0, endData.Length);
        ms.Seek(0, SeekOrigin.Begin);
        request.ContentLength = ms.Length;
    
        AsyncCallback requestCallback = new AsyncCallback((iar) =>
        {
            using (Stream stream = request.EndGetRequestStream(iar))
            {
                ms.CopyTo(stream);
            }
            request.BeginGetResponse(
             new AsyncCallback(ResponseCallback),
             Tuple.Create<HttpWebRequest, Type, Delegate>(request, typeof(TResult), responseCallback));
        });
        request.BeginGetRequestStream(requestCallback, request);
    }
    

    具体序列化字符串的方法为

    private static byte[] SerializeStrParameter(string boundary, string parameterName, string parameter)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("-----------------------------" + boundary);
        sb.AppendLine(string.Format("Content-Disposition: form-data; name=\"{0}\"", parameterName));
        sb.AppendLine();
        sb.AppendLine(parameter);
        return Encoding.UTF8.GetBytes(sb.ToString());
    }
    

    序列化byte数组(可用于提交文件)方法为

    private static byte[] SerializeBinParameter(string boundary, string parameterName, byte[] parameter)
    {
        if (parameter == null)
        {
            return new byte[0];
        }
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("-----------------------------" + boundary);
        sb.AppendLine(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"fakeFile.bin\"", parameterName));
        sb.AppendLine("Content-Type: application/octet-stream");
        sb.AppendLine();
        byte[] strBin = Encoding.UTF8.GetBytes(sb.ToString());
        byte[] rt = Encoding.UTF8.GetBytes("\r\n");
        byte[] re = new byte[strBin.Length + parameter.Length + rt.Length];
        Array.Copy(strBin, re, strBin.Length);
        Array.Copy(parameter, 0, re, strBin.Length, parameter.Length);
        Array.Copy(rt, 0, re, strBin.Length + parameter.Length, rt.Length);
        return re;
    }
    

    序列化对象方法为

    private static byte[] SerializeObjectParameter(string boundary, object parameter, string initialName = "")
    {
        if (parameter == null)
        {
            return new byte[0];
        }
        MemoryStream ms = new MemoryStream();
        var propertys = parameter.GetType()
            .GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.SetProperty);
        initialName = string.IsNullOrEmpty(initialName) ? "" : initialName + ".";
        foreach (var property in propertys)
        {
            if (property.PropertyType.IsArray)
            {
                Array array = (Array)property.GetValue(parameter, null);
                for (int i = 0; i < array.Length; i++)
                {
                    var data = SerializeObjectParameter(
                        boundary,
                        array.GetValue(i),
                        string.Format("{0}{1}[{2}]", initialName, property.Name, i));
                    ms.Write(data, 0, data.Length);
                }
            }
            else if (property.PropertyType.IsValueType || property.PropertyType == typeof(string))
            {
                var data = SerializeStrParameter(
                    boundary, 
                    initialName + property.Name,
                    property.GetValue(parameter, null).ToString());
                ms.Write(data, 0, data.Length);
            }
            else
            {
                throw new Exception();
            }
        }
    
        return ms.ToArray();
    }
    

     

posted on 2013-06-14 13:50  beastplus  阅读(898)  评论(0编辑  收藏  举报

导航