【问题标题】:Error: System.InvalidOperationException in ASP.NET WebAPI错误:ASP.NET WebAPI 中的 System.InvalidOperationException
【发布时间】:2015-06-06 04:29:35
【问题描述】:

我正在尝试将一些数据输入数据库并在成功调用结束时获取 access_token。

当我通过这个参数进行调用时:

一切顺利,用户注册并存入数据库,access_token返回给用户:

但是,当我在 deviceId 值中添加符号 +、= 或 \ 时,我得到异常并且没有任何内容保存在数据库中:

{
    "message": "An error has occurred.",
    "exceptionMessage": "Error getting value from 'ReadTimeout' on 'Microsoft.Owin.Host.SystemWeb.CallStreams.InputStream'.",
    "exceptionType": "Newtonsoft.Json.JsonSerializationException",
    "stackTrace": "   at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)\r\n   at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)\r\n   at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value)\r\n   at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n   at System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n   at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content)\r\n   at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n   at System.Web.Http.Owin.HttpMessageHandlerAdapter.<BufferResponseContentAsync>d__13.MoveNext()",
    "innerException": {
        "message": "An error has occurred.",
        "exceptionMessage": "Timeouts are not supported on this stream.",
        "exceptionType": "System.InvalidOperationException",
        "stackTrace": "   at System.IO.Stream.get_ReadTimeout()\r\n   at Microsoft.Owin.Host.SystemWeb.CallStreams.DelegatingStream.get_ReadTimeout()\r\n   at GetReadTimeout(Object )\r\n   at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)"
    }
}

这是此调用的模型定义:

public class Registration
    {
        public string UserName { get; set; }
        public string Password{ get; set; }
        public string DeviceId { get; set; }
        public string DeviceName { get; set; }
    }

字段 deviceId 作为用户名保存到数据库中,根据它的定义,它是 NVARCHAR(1024)

NVARCHAR 是否可能不允许非字母和数字的字符?其他人有这样的问题吗?

编辑:这是问题所在的方法:

[Route("registration/request")]
public async Task<HttpResponseMessage> RegistrationRequest(Registration model)
{
    try
    {
        MatrixLogManager.Info("Starting token creating.");

        var request = HttpContext.Current.Request;
        var tokenServiceUrl = request.Url.GetLeftPart(UriPartial.Authority) + request.ApplicationPath + "/Token";

        MatrixLogManager.Info("Checking if model is valid.");
        if (!ModelState.IsValid)
        {
            return Request.CreateResponse(BadRequest(ModelState));
        }
        using (MatrixServiceLayerLogin login = new MatrixServiceLayerLogin())
        {
            if (login.LoginUser(model.UserName, model.Password, true, true))
            {
                var personId = login.GetPersonId();

                MatrixLogManager.Debug("User " + model.UserName + "successfully logged in on MatrixSTS.");
                try
                {
                    using (var authRepo = new AuthRepository())
                    {
                        ApplicationUser appUser = new UserFactory().CreateApplicationUser(model, personId);
                        IdentityResult result = await authRepo.RegisterUser(appUser);
                        EMailService.SendEmail(appUser);
                        IHttpActionResult errorResult = GetErrorResult(result);

                        if (errorResult != null)
                        {
                            return Request.CreateResponse(errorResult);
                        }

                        using (var client = new HttpClient())
                        {
                            var requestParams = new List<KeyValuePair<string, string>>
                                                {
                                                    new KeyValuePair<string, string>("grant_type", "password"),
                                                    new KeyValuePair<string, string>("username", appUser.UserName),
                                                    new KeyValuePair<string, string>("password", "0000")
                                                };

                            var requestParamsFormUrlEncoded = new FormUrlEncodedContent(requestParams);
                            var tokenServiceResponse = await client.PostAsync(tokenServiceUrl, requestParamsFormUrlEncoded);
                            var responseString = await tokenServiceResponse.Content.ReadAsStringAsync();
                            var responseCode = tokenServiceResponse.StatusCode;
                            var responseMsg = new HttpResponseMessage(responseCode)
                            {
                                Content = new StringContent(responseString, Encoding.UTF8, "application/json")
                            };

                            responseMsg.Headers.Add("PSK", appUser.PSK);
                            return responseMsg;
                        }
                    }
                }
                catch (Exception ex)
                {
                    MatrixLogManager.Error("Error: ", ex);
                    throw ex;
                }
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid username or password.");
            }
        }
    }
    catch (Exception ex)
    {
        MatrixLogManager.Error(string.Format("Error while trying registring user: Exception = {0} InnerException {1}", ex.Message, ex.InnerException.Message));
        throw;
    }
}

Try-Catch 没有捕捉到任何异常,真正的异常发生在这里:

public async Task<IdentityResult> RegisterUser(ApplicationUser userModel)
{
    userModel.TwoFactorEnabled = true;
    userModel.PSK = TimeSensitivePassCode.GeneratePresharedKey();

    var result = await _userManager.CreateAsync(userModel, "0000");

    return result;
}

当结果所在的行返回给客户端时。我猜以前排队的储蓄并不顺利。我将在该部分代码中设置 try-catch 并发布异常。

【问题讨论】:

  • 问题的标题和文字完全不相关。实际的问题是什么?产生此错误的控制器代码在哪里?无论如何,NVARCHAR 是 Unicode - 它甚至允许汉字
  • 同时调试应用程序并发布实际的堆栈跟踪,而不是 Json 中的图像或扁平文本。这种形式的堆栈跟踪是不可读的。
  • @PanagiotisKanavos 感谢您的回答......我不知道如何命名或如何称呼这个问题......问题是:这种行为的可能原因是什么?以及如何解决它...为什么那些歌会造成问题...
  • 发布代码。调试它并发布异常的内容,包括堆栈跟踪。否则我们只能猜测。我的猜测是,您正在尝试返回一个使用延迟加载的实体框架对象,但我无法读取堆栈跟踪
  • 这与数据库无关。这与发布的数据有关。这将与某些具有其他含义的字符有关。即 cookie 中的“=”是分隔符。

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


【解决方案1】:

我看不到您的完整实现,但如果我有根据的猜测,您可能会尝试调用您的登录例程,该例程返回一个 HttpResponseMessage 数据类型(来自您的 Register 例程)。这两种方法都使用 Request.CreateResponse 来创建响应。

看到问题是,您正在尝试序列化一个已经序列化的 HttpResponseMessage。您的 Login 方法将调用 Request.CreateResponse 来创建 HttpResponseMessage ,您可能只是转身并“传递”到您的 Register 方法(但可能会通过另一个 Request.CreateResponse 方法调用来汇集它 --- 这是您进入的地方麻烦)。这是一个“隐含”的错误,很难发现——就像一个棋手盯着棋盘几个小时。

现在解决方案: 只需将登录方法的结果作为注册方法的结果传递,而不通过 Request.CreateResponse 方法“处理”它。如果您是 Rest 返回状态码的纯粹主义者,您可以在返回 Register 方法之前先更改返回的状态码(因为 Login 很可能有 OK [200] 的状态码 - 而最好的做法是返回 CREATED [ 201]在寄存器休息端点)。

【讨论】:

    【解决方案2】:

    这通常发生在您将响应包装两次时。

    考虑您的方法返回Task&lt;IHttpActionResult&gt; 而不是Task&lt;HttpResponseMessage&gt;,并注意在调用时您是如何将errorResult 包装两次的:

    return Request.CreateResponse(errorResult);
    

    这可能会让你相信你的令牌服务中的错误导致了这个问题,而实际上双重包装是:)

    考虑以下几点:

    [Route("registration/request")]
    public async Task<IHttpResult> RegistrationRequest(Registration model)
    {
        try
        {
            MatrixLogManager.Info("Starting token creating.");
    
            var request = HttpContext.Current.Request;
            var tokenServiceUrl = request.Url.GetLeftPart(UriPartial.Authority) + request.ApplicationPath + "/Token";
    
            MatrixLogManager.Info("Checking if model is valid.");
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            using (MatrixServiceLayerLogin login = new MatrixServiceLayerLogin())
            {
                if (login.LoginUser(model.UserName, model.Password, true, true))
                {
                    var personId = login.GetPersonId();
    
                    MatrixLogManager.Debug("User " + model.UserName + "successfully logged in on MatrixSTS.");
                    try
                    {
                        using (var authRepo = new AuthRepository())
                        {
                            ApplicationUser appUser = new UserFactory().CreateApplicationUser(model, personId);
                            IdentityResult result = await authRepo.RegisterUser(appUser);
                            EMailService.SendEmail(appUser);
                            IHttpActionResult errorResult = GetErrorResult(result);
    
                            if (errorResult != null)
                            {
                                // MAJOR CHANGE here
                                return errorResult;
                            }
    
                            using (var client = new HttpClient())
                            {
                                var requestParams = new List<KeyValuePair<string, string>>
                                                    {
                                                        new KeyValuePair<string, string>("grant_type", "password"),
                                                        new KeyValuePair<string, string>("username", appUser.UserName),
                                                        new KeyValuePair<string, string>("password", "0000")
                                                    };
    
                                var requestParamsFormUrlEncoded = new FormUrlEncodedContent(requestParams);
                                var tokenServiceResponse = await client.PostAsync(tokenServiceUrl, requestParamsFormUrlEncoded);
                                var responseString = await tokenServiceResponse.Content.ReadAsStringAsync();
                                var responseCode = tokenServiceResponse.StatusCode;
                                var responseMsg = new HttpResponseMessage(responseCode)
                                {
                                    Content = new StringContent(responseString, Encoding.UTF8, "application/json")
                                };
    
                                responseMsg.Headers.Add("PSK", appUser.PSK);
                                return responseMsg;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MatrixLogManager.Error("Error: ", ex);
                        throw ex;
                    }
                }
                else
                {
                    return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid username or password.");
                }
            }
        }
        catch (Exception ex)
        {
            MatrixLogManager.Error(string.Format("Error while trying registring user: Exception = {0} InnerException {1}", ex.Message, ex.InnerException.Message));
            throw;
        }
    }
    

    【讨论】:

    • This usually happens when you're wrapping a Response twice.宾果游戏!
    猜你喜欢
    • 2013-02-03
    • 2014-01-04
    • 2017-05-16
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    • 2019-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多