参考网址: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了。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)