查看: 2285|回复: 0

[ASP.NET教程] WebApi返回Json格式字符串

发表于 2017-1-9 08:00:01

WebApi返回json格式字符串, 在网上能找到好几种方法, 其中有三种普遍的方法, 但是感觉都不怎么好.

先贴一下, 网上给的常用方法吧.

方法一:(改配置法)

找到Global.asax文件,在Application_Start()方法中添加一句:

复制代码
  1. protected void Application_Start()
  2. {
  3. AreaRegistration.RegisterAllAreas();
  4. WebApiConfig.Register(GlobalConfiguration.Configuration);
  5. FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
  6. RouteConfig.RegisterRoutes(RouteTable.Routes);
  7. // 使api返回为json
  8. GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
  9. }
复制代码
复制代码

这样返回的结果就都是json类型了,但有个不好的地方,如果返回的结果是String类型,如123,返回的json就会变成"123";


解决的方法是自定义返回类型(返回类型为HttpResponseMessage)

复制代码
  1. public HttpResponseMessage PostUserName(User user)
  2. {
  3. String userName = user.userName;
  4. var result = new HttpResponseMessage{ Content = new StringContent(userName,Encoding.GetEncoding("UTF-8"), "application/json")};
  5. return result;
  6. }
复制代码
复制代码

方法二:(万金油法)

方法一中又要改配置,又要处理返回值为String类型的json,甚是麻烦,不如就不用webapi中的的自动序列化对象,自己序列化后再返回

复制代码
  1. public HttpResponseMessage PostUser(User user)
  2. {
  3. JavaScriptSerializer serializer = new JavaScriptSerializer();
  4. string str = serializer.Serialize(user);
  5. HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(str, Encoding.GetEncoding("UTF-8"), "application/json") };
  6. return result;
  7. }
复制代码
复制代码

为了不在每个接口中都反复写那几句代码,所以就封装为一个方法这样使用就方便多了。

复制代码
  1. public static HttpResponseMessage toJson(Object obj)
  2. {
  3. String str;
  4. if (obj is String ||obj is Char)
  5. {
  6. str = obj.ToString();
  7. }
  8. else
  9. {
  10. JavaScriptSerializer serializer = new JavaScriptSerializer();
  11. str = serializer.Serialize(obj);
  12. }
  13. HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(str, Encoding.GetEncoding("UTF-8"), "application/json") };
  14. return result;
  15. }
复制代码
复制代码

方法三:(最麻烦的方法)

方法一最简单,但杀伤力太大,所有的返回的xml格式都会被毙掉,那么方法三就可以只让api接口中毙掉xml,返回json

先写一个处理返回的类:

复制代码
  1. public class JsonContentNegotiator : IContentNegotiator
  2. {
  3. private readonly JsonMediaTypeFormatter _jsonFormatter;
  4. public JsonContentNegotiator(JsonMediaTypeFormatter formatter)
  5. {
  6. _jsonFormatter = formatter;
  7. }
  8. public ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
  9. {
  10. var result = new ContentNegotiationResult(_jsonFormatter, new MediaTypeHeaderValue("application/json"));
  11. return result;
  12. }
  13. }
复制代码
复制代码

找到App_Start中的WebApiConfig.cs文件,打开找到Register(HttpConfiguration config)方法

添加以下代码:

  1. var jsonFormatter = new JsonMediaTypeFormatter();
  2. config.Services.Replace(typeof(IContentNegotiator), new JsonContentNegotiator(jsonFormatter));
复制代码

添加后代码如下:

复制代码
  1. public static void Register(HttpConfiguration config)
  2. {
  3. config.Routes.MapHttpRoute(
  4. name: "DefaultApi",
  5. routeTemplate: "api/{controller}/{action}/{id}",
  6. defaults: new { id = RouteParameter.Optional }
  7. );
  8. var jsonFormatter = new JsonMediaTypeFormatter();
  9. config.Services.Replace(typeof(IContentNegotiator), new JsonContentNegotiator(jsonFormatter));
  10. }
复制代码
复制代码

方法三如果返回的结果是String类型,如123,返回的json就会变成"123",解决方法同方法一。

其实WebApi会自动把返回的对象转为xml和json两种格式并存的形式,方法一与方法三是毙掉了xml的返回,而方法二是自定义返回。

以上三种方法, 就是我找到的比较普遍的方法了. 但是总觉得并不是那么好. 都要改这改那的.

还有一种方式能返回json格式字符串. 先看一下效果吧.

  1. public class HomeController : ApiController
  2. {
  3. [HttpGet]
  4. public JsonData Know(string msg)
  5. {
  6. msg = "WebApi 已接收到信息" ;
  7. return new JsonData() { Content = new List<string>() { "a", "b", "c" }, IsSuccess = true, Message = msg };
  8. }
  9. public List<string> Get()
  10. {
  11. return new List<string>() { "a", "b", "c"};
  12. }
  13. }
复制代码

看的出来, Know方法返回的是 json 格式的字符串, Get方法, 返回的是xml格式的.

从上面来看, 主要是返回值不一样. 那么JsonData里面有什么秘密呢?

  1. public class JsonData : ISerializable
  2. {
  3. #region 属性
  4. /// <summary>
  5. /// 表示业务是否正常
  6. /// </summary><br>  public bool IsSuccess { get; set; }
  7. /// <summary>
  8. /// 返回消息,成功的消息和错误消息都在这里
  9. /// </summary><br>  public string Message { get; set; }
  10. /// <summary>
  11. /// 用于返回复杂结果
  12. /// </summary><br>  public object Content { get; set; }
  13. #endregion
  14. #region 方法
  15. /// <summary>
  16. /// 自定义序列化方法
  17. /// </summary>
  18. /// <param name="info"></param>
  19. /// <param name="context"></param>
  20. public void GetObjectData(SerializationInfo info, StreamingContext context)
  21. {
  22. // 运用info对象来添加你所需要序列化的项
  23. info.AddValue("IsSuccess", IsSuccess);
  24. info.AddValue("Message", Message);
  25. if (Content != null)
  26. {
  27. info.AddValue("Content", Convert.ChangeType(Content, Content.GetType()));
  28. }
  29. else
  30. {
  31. info.AddValue("Content", null);
  32. }
  33. }
  34. public JsonData() { }
  35. #endregion
  36. }
复制代码

这里主要是要实现 ISerializable 接口 .

可能有人注意到, 我访问api的时候, 路由模式和访问mvc是一样的, 其实这里很简单, 只需要在webapi路由注册哪里, 加入一个路由就可以了.

  1. config.Routes.MapHttpRoute(
  2. name: "DefaultApi1",
  3. routeTemplate: "api/{controller}/{action}",
  4. defaults: new { id = RouteParameter.Optional }
  5. );
复制代码

这样, 就加入了一个路由匹配规则进去. 只不过, 需要在Know方法上面, 加上一些访问限制条件. 如httpget, 否则, 如果直接去访问, 是不可以的.



回复

使用道具 举报