WEB API返回的字符串列表

参考网址:https://www.cnblogs.com/yuanmo/p/10045467.html

开发工具:vs2015
语言:C# ASP.NET 5

第一次弄asp.net mvc,太难了,一堆问题

我的程序结构:web api->mvc5后台,即mvc5后台访问web api,获取到数据之后,显示到前端的页面上

web api接口代码如下:

public List<string> GetLocalDirs()
{
    List<string> retList = GetGoodDirs();
    if (retList.Count() == 0)
        retList.Add("-1:搜索目录失败");
    return retList;
}

这个接口返回的是一个字符串列表,如果没有搜索到目录,就一条数据:-1:搜索目录失败。在请求它的mvc5后台代码参考网上的内容,也很简单:

public ActionResult SearchDir()
{
    WebClient webClient = new WebClient();
    string remoteDirList = webClient.DownloadString(strRemoteUrl);
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(List<string>));
    MemoryStream ms = new MemoryStream(Encoding.Default.GetBytes(remoteDirList));
    List<string> listTmp = (List<string>)ser.ReadObject(ms);
    
    DirFindViewModel model = new DirFindViewModel();
    model.dirList = listTmp;
    return PartialView(model);
}

这个action是由js在页面后面请求。收到web api的返回内容后,反序列化为List<string>结构。通过调试发现,如果返回的字符串不带中文,即只有普通的英文符号(比如字母、数字等),就没有问题,如果有中文,就失败。后加了个try:

public ActionResult SearchDir()
{
    string remoteDirList = "";
    try
    {
        WebClient webClient = new WebClient();
        remoteDirList = webClient.DownloadString(strRemoteUrl);
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(List<string>));
        MemoryStream ms = new MemoryStream(Encoding.Default.GetBytes(remoteDirList));
        List<string> listTmp = (List<string>)ser.ReadObject(ms);
    
        DirFindViewModel model = new DirFindViewModel();
        model.dirList = listTmp;
        return PartialView(model);
    }
    catch(Exception e)
    {
        model.strDesc = e.Message;
        return PartialView(model);
    }
}

通过catch,发现是反序列化时失败,说什么格式不正确,同时发现 remoteDirList 的中文内容是乱码,这应该是编码的问题了,于是去网上找相关的说明,修改后的代码如下:

public ActionResult SearchDir()
{
    string remoteDirList = "";
    try
    {
        WebClient webClient = new WebClient();
        remoteDirList = webClient.DownloadString(strRemoteUrl);

        // 转换编码为unicode
        byte[] utf8Bytes = Encoding.Default.GetBytes(remoteDirList);
        byte[] defBytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, utf8Bytes);
        remoteDirList = Encoding.Default.GetString(defBytes);


        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(List<string>));
        MemoryStream ms = new MemoryStream(Encoding.Default.GetBytes(remoteDirList));
        List<string> listTmp = (List<string>)ser.ReadObject(ms);
    
        DirFindViewModel model = new DirFindViewModel();
        model.dirList = listTmp;
        return PartialView(model);
    }
    catch(Exception e)
    {
        model.strDesc = e.Message;
        return PartialView(model);
    }
}

再跟踪仍然失败,仔细看转换之后的字符串,发现前面的大部分是正常的,只有最后一个字会被转成??,即两个问号。反复捉摸,问了同事,参考网上的,既然web api返回List<string>在接收端是个字符串,那我直接改为返回字符串,修改后如下:

public string GetLocalDirs()
{
    List<string> retList = GetGoodDirs();
    if (retList.Count() == 0)
        retList.Add("-1:搜索目录失败");

    string retStr = Newtonsoft.Json.JsonConvert.SerializeObject(retList);
    return retStr;
}

改过之后,发现还是不行,原本正常的字符串,这次多出了转义符,比如修改之前返回的是:
["-1:搜索目录失??"],修改之后,返回的变成了:
"[\"-1:搜索目录失败\"]"
注意,这是实际的内容,如果是在调试模式下,在变量列表中显示的内容就是 “\"[\\\"-1:搜索目录失败\\\"]\"”,(两边的双引号是工具显示字符串的),这个就有点不可思议了,我在web api的接口中,把返回的retStr写入到文件中,查看它确实没错,并不存在黑底符。没办法,我就摒弃了库函数,直接自己实现,代码也很简单:

public string GetLocalDirs()
{
    List<string> retList = GetGoodDirs();
    if (retList.Count() == 0)
        retList.Add("-1:搜索目录失败");

    string retStr = "[";
    int txtIndex = 0;
    foreach(string itemText in retList)
    {
        if (txtIndex > 0)
            retStr += ",";
        retStr += "\"" + itemText + "\"";
        txtIndex++;
   }
   retStr += "]";

    return retStr;
}

这改过之后,仍然把返回的内容写入文件,查看和之前没啥区别,依然有转义符,没办法了,既然传输会带上转义符,那就在接收端把它去掉,修改代码如下:

public ActionResult SearchDir()
{
    string remoteDirList = "";
    try
    {
        WebClient webClient = new WebClient();
        remoteDirList = webClient.DownloadString(strRemoteUrl);

        // 转换编码为unicode
        byte[] utf8Bytes = Encoding.Default.GetBytes(remoteDirList);
        byte[] defBytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, utf8Bytes);
        remoteDirList = Encoding.Default.GetString(defBytes);
        remoteDirList = remoteDirList.Replace("\\", "");        // 加了这三行
        remoteDirList = remoteDirList.Replace("\"[", "[");
        remoteDirList = remoteDirList.Replace("]\"", "]");

        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(List<string>));
        MemoryStream ms = new MemoryStream(Encoding.Default.GetBytes(remoteDirList));
        List<string> listTmp = (List<string>)ser.ReadObject(ms);
    
        DirFindViewModel model = new DirFindViewModel();
        model.dirList = listTmp;
        return PartialView(model);
    }
    catch(Exception e)
    {
        model.strDesc = e.Message;
        return PartialView(model);
    }
}

再测试,转义符已经被成功清除掉了,现在还是有编码的问题,再仔细考虑,这个编码我点有混乱,在catch的提示信息中,有出现“utf8”的字样,那看来还是编码的问题导致的,对于http传输,不大可能丢失字节,就算丢,也不可能是每次都丢,并且丢的是中间的内容。再仔细查看编码的转换部分,把鼠标放在 Encoding.Default 的Default 上,提示是ANSI 代码页的编码,但是string提示又是unicode,加上catch提示中的utf8字样,难道是反序列化的编码不对?对它的编码进行修改,不再使用Default编码,修改后代码如下:

public ActionResult SearchDir()
{
    string remoteDirList = "";
    try
    {
        WebClient webClient = new WebClient();
        remoteDirList = webClient.DownloadString(strRemoteUrl);

        // 转换编码为unicode
        byte[] utf8Bytes = Encoding.Default.GetBytes(remoteDirList);
        byte[] defBytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, utf8Bytes);
        remoteDirList = Encoding.Default.GetString(defBytes);
        remoteDirList = remoteDirList.Replace("\\", "");
        remoteDirList = remoteDirList.Replace("\"[", "[");
        remoteDirList = remoteDirList.Replace("]\"", "]");

        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(List<string>));
        MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(remoteDirList));    // 改了编码
        List<string> listTmp = (List<string>)ser.ReadObject(ms);
    
        DirFindViewModel model = new DirFindViewModel();
        model.dirList = listTmp;
        return PartialView(model);
    }
    catch(Exception e)
    {
        model.strDesc = e.Message;
        return PartialView(model);
    }
}

注,这里只是修改了 MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(remoteDirList)); 一行中的编码,由Default改成了Unicode。然后再测试,一切ok,所有的中文也都能正常显示了,反序列化也不再被catch了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值