[英]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.