【问题标题】:How to deserialize json to .net type and return it as string如何将 json 反序列化为 .net 类型并将其作为字符串返回
【发布时间】:2013-12-23 23:02:37
【问题描述】:

我正在尝试使用 Fiddler 发送 POST 请求:

POST http://localhost:50196/api/values/json HTTP/1.1
User-Agent: Fiddler
Content-Type: application/json;
Host: localhost:50196
Content-Length: 73

{"ssn":1605789787,"creditScore":598,"loanAmount":10.0,"loanDuration":360}

这是我的 WebAPI 控制器,我将其反序列化为 .NET 类型,即我的 POCO。然后我得到 ssn 并生成一个我想返回的费率。

public class ValuesController : ApiController
{
    [ActionName("json")]
    public string Post(string request)
    {
        var json = JsonConvert.DeserializeObject<JsonModel>(request);
        var ss = json.Ssn;

        var random = new Random();
        var interestRate = random.Next(100, 500);
        var rate = interestRate / 100;

        var delta = "{\"ssn\":" + ss + ",\"interestRate\":" + rate + "}";

        return delta;

    }

}

POCO:

public class JsonModel
{
    [JsonProperty("ssn")]
    public string Ssn { get; set; }
    [JsonProperty("creditScore")]
    public int CreditScore { get; set; }
    [JsonProperty("loanAmount")]
    public decimal LoanAmount { get; set; }
    [JsonProperty("loanDuration")]
    public int LoanDuration { get; set; }
}

WebAPI 配置:

    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: new {action = @"[a-zA-Z]+", id = @"\*"}
        );
    }

这是我得到的错误:

[HttpException]: 路径 '/api/values/json' 的控制器 未找到或未实现 IController。已经 System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext,类型 controllerType) ved System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) ved System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext、IController&控制器、IControllerFactory&工厂) 已验证 System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext、AsyncCallback 回调、对象状态)已验证 System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback 回调,对象状态)ved
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext 上下文、AsyncCallback cb、对象 extraData) ved
System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 已验证 System.Web.HttpApplication.ExecuteStep(IExecutionStep 步骤, Boolean & completedSynchronously)

【问题讨论】:

    标签: c# json asp.net-web-api


    【解决方案1】:

    首先,您在这里完全错过了 ASP.NET MVC 模型绑定功能,而不是在操作中接受 JSON 字符串然后反序列化,只期望模型并让框架为您进行绑定,例如

    public HttpResponseMessage Post(JsonModel model)
    {
        ...
    }
    

    其次,您的例外是由于路由问题。您正在尝试发帖到api/values/json,这相当于api/{controller}/{action}。但是,正如您所见,您没有映射到该特定路由的操作,因为您唯一的路由需要一个 id 参数(但您的操作包含一个 request 参数)。

    切换到直接在视图中使用模型应该足以解决此问题,并且应该可以直接发布到api/values/json


    我认为{ id = RouteParameter.Optional } 是可选的,因为它会接受 ID

    通常情况就是这样,但是,在您的路线中,您在 id 上设置了一个约束,表示它必须包含 一些 值 - 这会使您的默认值过时。

    【讨论】:

    • 我认为{id = RouteParameter.Optional} 是可选的,因为它可以接受没有 ID。谢谢你的回答,干杯。
    • 感谢您的进一步解释,感谢:)
    【解决方案2】:

    我认为您的控制器可以直接接受您的 POCO 类型,无需手动从字符串中序列化:

    public HttpResponseMessage Post(HttpRequestMessage request, [FromBody]JsonModel)
    

    不过,我不确定这是否是问题所在。使用 WebAPI 时,我会远离 ActionName 属性。我认为使用简单的 Get/Post 等方法为每种类型都有一个单独的控制器要干净得多。所以,在你的情况下:

    控制器:

    public HttpResponseMessage Post(HttpRequestMessage request, [FromBody]JsonModel)
    {}
    

    然后您只需发布到:

    api/values
    

    ...最后,您的路线配置:

    routeTemplate: "api/{controller}/{id}"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多