簡體   English   中英

錯誤:ASP.NET WebAPI中的System.InvalidOperationException

[英]Error: System.InvalidOperationException in ASP.NET WebAPI

我正在嘗試將一些數據輸入數據庫並在成功調用結束時獲取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以UserName的形式保存到數據庫中,根據它的定義,它是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,我將發布異常。

當您將響應包裝兩次時,通常會發生這種情況。

考慮你的方法返回Task<IHttpActionResult>而不是Task<HttpResponseMessage>並注意你在調用時如何包裝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;
    }
}

我看不到你的完整實現,但如果我采取有根據的猜測,你可能會嘗試調用你的登錄例程,它會返回一個HttpResponseMessage數據類型(來自你的Register例程)。 這兩種方法都使用Request.CreateResponse來創建響應。

看問題是,您正在嘗試序列化已經序列化的HttpResponseMessage。 您的Login方法將調用Request.CreateResponse來創建HttpResponseMessage,您可能只需轉向並“傳遞”到您的Register方法(但很可能通過另一個Request.CreateResponse方法調用匯集它 - 這是您進入的地方麻煩)。 這是一個“隱含”的錯誤,很難捕捉到 - 像棋手一樣盯着國際象棋棋盤幾個小時。

現在解決方案:只需將登錄方法的結果作為register方法的結果傳遞,而不通過Request.CreateResponse方法“處理”它。 如果您是Rest返回狀態代碼的純粹主義者,則可以在返回Register方法之前更改返回的狀態代碼(因為Login可能具有OK [200]的狀態代碼 - 而更好的做法是返回CREATED [ 201]在注冊休息終點)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM