Asp.NETWebAPI处理post请求大约需要2分钟
当我试图发布(或放置)我的viewModel时,通过JSON表示Asp.NETWebAPI处理post请求大约需要2分钟,asp.net,.net,visual-studio,asp.net-web-api,iis-express,Asp.net,.net,Visual Studio,Asp.net Web Api,Iis Express,当我试图发布(或放置)我的viewModel时,通过JSON表示 PUT /adm/api/places/1 HTTP/1.1 Host: localhost:11483 Content-Type: application/json Content-Length: 64 { id: 1, name: "000000", description: "des1", published: false } 给我的控制器 [Route("adm/api/places", Name =
PUT /adm/api/places/1 HTTP/1.1
Host: localhost:11483
Content-Type: application/json
Content-Length: 64
{
id: 1,
name: "000000",
description: "des1",
published: false
}
给我的控制器
[Route("adm/api/places", Name = "PlacesApi")]
public object PostPlace(PlaceVM place)
{
// breakpoint hits here only after about 2 minutes
}
在控制器的操作开始处理请求之前,我必须等待大约2分钟。
我发现造成这种情况的原因是对.net framework函数System.Security.Cryptography.CapiHashAlgorithm.HashCore的多次调用:
[SecuritySafeCritical]
public void HashCore(byte[] array, int ibStart, int cbSize)
{
Contract.Assert(m_hashHandle != null);
if (array == null) {
throw new ArgumentNullException("array");
}
if (ibStart < 0 || ibStart > array.Length - cbSize) {
throw new ArgumentOutOfRangeException("ibStart");
}
if (cbSize < 0 || cbSize > array.Length) {
throw new ArgumentOutOfRangeException("cbSize");
}
byte[] hashData = new byte[cbSize];
Buffer.BlockCopy(array, ibStart, hashData, 0, cbSize);
if (!CapiNative.UnsafeNativeMethods.CryptHashData(m_hashHandle, hashData, cbSize, 0)) {
throw new CryptographicException(Marshal.GetLastWin32Error());
}
}
[SecuritySafeCritical]
public void HashCore(字节[]数组,int-ibStart,int-cbSize)
{
Assert(m_hashHandle!=null);
if(数组==null){
抛出新的ArgumentNullException(“数组”);
}
if(ibStart<0 | | ibStart>array.Length-cbSize){
抛出新ArgumentOutOfRangeException(“ibStart”);
}
if(cbSize<0 | | cbSize>array.Length){
抛出新ArgumentOutOfRangeException(“cbSize”);
}
字节[]哈希数据=新字节[cbSize];
BlockCopy(数组、ibStart、hashData、0、cbSize);
if(!capinive.unsafentiveMethods.CryptHashData(m_hashHandle,hashData,cbSize,0)){
抛出新的加密异常(Marshal.GetLastWin32Error());
}
}
参数“array”包含大小约为5 MB的字节数组
调用堆栈如下所示:
[管理到本机转换]
System.Core.dll!System.Security.Cryptography.CapiHashAlgorithm.HashCore(字节[])
数组,int-ibStart,int-cbSize)第124行C#
System.Core.dll!System.Security.Cryptography.SHA256CryptoServiceProvider.HashCore(字节[])
数组,int-ibStart,int-cbSize)第51行C#
mscorlib.dll!System.Security.Cryptography.HashAlgorithm.ComputeHash(字节[])
缓冲区)第85行C#
mscorlib.dll!System.Security.Policy.Hash.GenerateHash(System.Type
hashType,byte[]assemblyBytes)第338行C#
mscorlib.dll!System.Security.Policy.Hash.GenerateHash(System.Type
hashType)第316行C#
mscorlib.dll!System.Security.Policy.Hash.SHA256.get()行255 C#
[轻量级功能]System.Web.Http.dll!System.Web.Http.Metadata.Providers.AssociatedMetadataProvider.GetMetadataForPropertiesImpl.AnonymousMethod__0()未知 System.Web.Http.dll!System.Web.Http.Metadata.ModelMetadata.Model.get()未知 System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(System.Web.Http.Metadata.ModelMetadata 元数据, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext,对象容器, System.Collections.Generic.IEnumerable 验证程序)未知 System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(System.Web.Http.Metadata.ModelMetadata 元数据, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext)未知 System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(System.Web.Http.Metadata.ModelMetadata 元数据, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext,对象容器, System.Collections.Generic.IEnumerable 验证程序)未知 System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateElements(System.Collections.IEnumerable 模型 System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext)未知 System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(System.Web.Http.Metadata.ModelMetadata 元数据, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext,对象容器, System.Collections.Generic.IEnumerable 验证程序)未知 System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(System.Web.Http.Metadata.ModelMetadata 元数据, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext)未知 System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(System.Web.Http.Metadata.ModelMetadata 元数据, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext,对象容器, System.Collections.Generic.IEnumerable 验证程序)未知 System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(System.Web.Http.Metadata.ModelMetadata 元数据, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext)未知 System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(System.Web.Http.Metadata.ModelMetadata 元数据, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext,对象容器, System.Collections.Generic.IEnumerable 验证程序)未知 System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(System.Web.Http.Metadata.ModelMetadata 元数据, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext)未知 System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(System.Web.Http.Metadata.ModelMetadata 元数据, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext,对象容器, System.Collections.Generic.IEnumerable 验证程序)未知 System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(System.Web.Http.Metadata.ModelMetadata 元数据, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext)未知 System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(System.Web.Http.Metadata.ModelMetadata 元数据, System.Web.Http
public class PlaceVM : ViewModelBase<Place>
{
public PlaceVM()
{
}
public PlaceVM(Place place)
{
ID = place.ID;
Name = place.Name;
Description = place.Description;
PlaceTypeID = place.PlaceTypeID;
Published = place.Published;
}
[EpHiddenField]
public long? ID { get; set; }
[Required]
[StringLength(100)]
[EpTextField(Caption = "Название")]
public string Name { get; set; }
[Required]
[StringLength(512, MinimumLength = 30)]
[EpTextAreaField(Caption = "Описание")]
public string Description { get; set; }
[Required]
[EpLookupField("placeTypes", Caption = "Тип")]
public long? PlaceTypeID { get; set; }
[EpCheckFiled(Caption = "Опубликовано")]
public bool? Published { get; set; }
}
public abstract class ViewModelBase<TEntity> where TEntity : class, IEntity, new()
{
private class VmAndEntity
{
public PropertyInfo ViewModelProp { get; set; }
public PropertyInfo EntityProp { get; set; }
}
private static readonly log4net.ILog _log =
log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected TEntity _Model;
protected ViewModelBase(TEntity model, bool fillVmByPropsMap = false)
{
if (model == null) // При вызовае JSON.NET сериализатором
{
model = new TEntity();
}
_Model = model;
LazyInitializer.EnsureInitialized(ref _entityPropsGetters, () => GetEntityPropGetters(this.GetType()));
if (fillVmByPropsMap)
FillVMByPropsMap(model);
}
[JsonIgnore]
public Expression<Func<TEntity, object>>[] EntityPropsGetters
{
get
{
if (_entityPropsGetters == null)
throw new EpFieldNotInitializedException("_entityPropsGetters");
return _entityPropsGetters;
}
}
private static Expression<Func<TEntity, object>>[] _entityPropsGetters;
protected void FillVMByPropsMap(TEntity model)
{
if (model == null)
return;
if (_vmToEntityPropsMap.Count == 0)
{
_log.WarnFormat("_vmToEntityPropsMap is empty for VM '{0}'", this.GetType());
#if DEBUG
throw new EpInvalidStateException("VM '{0}' has no properties which fit model's properties");
#endif
}
foreach (var vmAndEntity in _vmToEntityPropsMap)
{
var val = vmAndEntity.EntityProp.GetValue(model, null);
vmAndEntity.ViewModelProp.SetValue(this, val);
}
}
public abstract TEntity FillModel();
protected TEntity FillModelByPropsMap()
{
if (_vmToEntityPropsMap.Count == 0)
{
_log.WarnFormat("_vmToEntityPropsMap is empty for VM '{0}'", this.GetType());
#if DEBUG
throw new EpInvalidStateException("VM '{0}' has no properties which fit model's properties");
#endif
}
if (_Model == null)
_Model = new TEntity();
foreach (var vmAndEntity in _vmToEntityPropsMap)
{
var val = vmAndEntity.ViewModelProp.GetValue(this);
vmAndEntity.EntityProp.SetValue(_Model, val);
}
return _Model;
}
private static List<VmAndEntity> _vmToEntityPropsMap;
private static Expression<Func<TEntity, object>>[] GetEntityPropGetters(Type vmType)
{
List<Expression<Func<TEntity, object>>> res = new List<Expression<Func<TEntity, object>>>();
_vmToEntityPropsMap = new List<VmAndEntity>();
var vmProperties = vmType.GetProperties().Where(p => p.CanRead);
var eProperties = typeof(TEntity).GetProperties().Where(p => p.CanRead);
foreach (var vmProp in vmProperties)
{
var eProp = eProperties.FirstOrDefault(item => item.Name == vmProp.Name);
// Если в модели нашлось свойство, соотвествующее ViewModelProp, то
if (eProp != null)
{
_vmToEntityPropsMap.Add(new VmAndEntity() { ViewModelProp = vmProp, EntityProp = eProp});
// получим Expression для доступа к этому свойству
var parameter = Expression.Parameter(typeof(TEntity));
var property = Expression.Property(parameter, eProp);
Expression conversion = Expression.Convert(property, typeof(object));
var lambda = Expression.Lambda<Func<TEntity, object>>(conversion, parameter);
res.Add(lambda);
}
}
return res.ToArray();
}
}