csharp ASP.NET的助手,ASP.NET MVC应用服务器端测试
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp ASP.NET的助手,ASP.NET MVC应用服务器端测试相关的知识,希望对你有一定的参考价值。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Hosting;
using System.Web.Routing;
/// <summary>
/// Allow to run and communicate with ASP.NET application in separate app domain (memory is not shared).
/// Required for UnitTests. Had to place it here, because it does not load test assembly otherwise.
/// (http://stackoverflow.com/questions/1373100/how-to-add-folder-to-assembly-search-path-at-runtime-in-net
/// alternative was either to create a copy script puting test assemblies in bin folder, or register test assembly in GAC)
/// Taken from here: https://lostechies.com/chadmyers/2008/06/25/hosting-an-entire-asp-net-mvc-request-for-testing-purposes/
/// </summary>
[System.Diagnostics.DebuggerStepThrough]
public class WebAppHostHelper : MarshalByRefObject
{
public static WebAppHostHelper Create(string webAppDir)
{
///More flexible way is here: http://weblog.west-wind.com/posts/2005/Jul/20/AspNET-Runtime-Hosting-Update
var res = System.Web.Hosting.ApplicationHost.CreateApplicationHost(typeof(WebAppHostHelper), "/", webAppDir) as WebAppHostHelper;
return res;
}
public WebAppHostHelper()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
}
public void SetAssemblyLocations(params string[] binPaths)
{
this.binPaths = binPaths;
}
public void LoadAssemblies(params string[] assemblyFiles)
{
assemblyFiles.ToList().ForEach(a => {
Assembly.LoadFrom(a);
});
}
string[] binPaths = null;
private System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var lookingForFilename = new AssemblyName(args.Name).Name+".dll";
var dirs = (binPaths?? Enumerable.Empty<string>()).Select(bp => new DirectoryInfo(bp));
foreach (var dir in dirs)
{
var assemblyFile = dir.GetFiles().FirstOrDefault(f=>string.Equals(f.Name, lookingForFilename, StringComparison.InvariantCultureIgnoreCase));
if (assemblyFile != null)
return Assembly.LoadFrom(assemblyFile.FullName);
}
return null;
}
public object CreateInstance(Type type, params object[] args)
{
return Activator.CreateInstance(type, args: args);
}
public AppDomain GetAppDomain()
{
return AppDomain.CurrentDomain;
}
public override object InitializeLifetimeService()
{
// This tells the CLR not to surreptitiously
// destroy this object -- it's a singleton
// and will live for the life of the appdomain
return null;
}
/// <summary>
/// Wake up ASP.NET
/// </summary>
/// <param name="relativeUrl"></param>
/// <returns></returns>
public string WakeUpAspNetMvc(string relativeUrl = null)
{
using (var response = new StringWriter())
{
HttpRuntime.ProcessRequest(new SimpleWorkerRequest(relativeUrl ?? "/", "", response));
response.Flush();
return response.ToString();
}
}
public string ProcessRequest(string url, string query)
{
var writer = new StringWriter();
var request = new SimpleWorkerRequest(url, query, writer);
var context = HttpContext.Current = new HttpContext(request);
var contextBase = new HttpContextWrapper(context);
var routeData = RouteTable.Routes.GetRouteData(contextBase);
var routeHandler = routeData.RouteHandler;
var requestContext = new RequestContext(contextBase, routeData);
var httpHandler = routeHandler.GetHttpHandler(requestContext);
httpHandler.ProcessRequest(context);
context.Response.End();
writer.Flush();
return writer.GetStringBuilder().ToString();
}
protected internal T Invoke<T>(SerializableDelegate<Func<WebAppHostHelper, T>> func)
{
if (func == null || func.Delegate==null)
throw new SerializationException("Could not serialize your delegate for cross domain execution");
return func.Delegate(this);
}
protected internal void Invoke(SerializableDelegate<Action<WebAppHostHelper>> action)
{
if (action == null || action.Delegate == null)
throw new SerializationException("Could not serialize your delegate for cross domain execution");
action.Delegate(this);
}
}
[System.Diagnostics.DebuggerStepThrough]
public static class WebAppHostHelperExtensions
{
public static T Invoke<T>(this WebAppHostHelper host, Func<WebAppHostHelper,T> crossDomainAction)
{
var serDel = new SerializableDelegate<Func<WebAppHostHelper, T>>(crossDomainAction);
return host.Invoke(serDel);
}
public static void Invoke(this WebAppHostHelper host, Action<WebAppHostHelper> crossDomainAction)
{
var serDel = new SerializableDelegate<Action<WebAppHostHelper>>(crossDomainAction);
host.Invoke(serDel);
}
}
/// <summary>
/// Makes delegates serializable where possible
/// Taken from here:
/// https://github.com/chrisortman/MvcIntegrationTest/blob/master/src/MvcIntegrationTestFramework/Hosting/SerializableDelegate.cs
/// Used to pass test delegates from the test appdomain into the ASP.NET host appdomain
/// Adapted from http://www.codeproject.com/KB/cs/AnonymousSerialization.aspx
/// </summary>
[Serializable]
[System.Diagnostics.DebuggerStepThrough]
public class SerializableDelegate<TDelegate> : ISerializable where TDelegate : class
{
public TDelegate Delegate { get; private set; }
internal SerializableDelegate(TDelegate @delegate)
{
Delegate = @delegate;
}
internal SerializableDelegate(SerializationInfo info, StreamingContext context)
{
var delegateType = (Type)info.GetValue("delegateType", typeof(Type));
if (info.GetBoolean("isSerializable"))
//If it's a "simple" delegate we just read it straight off
Delegate = (TDelegate)info.GetValue("delegate", delegateType);
else {
//otherwise, we need to read its anonymous class
var methodInfo = (MethodInfo)info.GetValue("method", typeof(MethodInfo));
var anonymousClassWrapper = (AnonymousClassWrapper)info.GetValue("class", typeof(AnonymousClassWrapper));
Delegate = (TDelegate)(object)System.Delegate.CreateDelegate(delegateType, anonymousClassWrapper.TargetInstance, methodInfo);
}
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("delegateType", Delegate.GetType());
var untypedDelegate = (Delegate)(object)Delegate;
//If it's an "simple" delegate we can serialize it directly
if ((untypedDelegate.Target == null || untypedDelegate.Method.DeclaringType.GetCustomAttributes(typeof(SerializableAttribute), false).Length > 0) && Delegate != null)
{
info.AddValue("isSerializable", true);
info.AddValue("delegate", Delegate);
}
else {
//otherwise, serialize anonymous class
info.AddValue("isSerializable", false);
info.AddValue("method", untypedDelegate.Method);
info.AddValue("class", new AnonymousClassWrapper(untypedDelegate.Method.DeclaringType, untypedDelegate.Target));
}
}
[Serializable]
private class AnonymousClassWrapper : ISerializable
{
public object TargetInstance { get; private set; }
private readonly Type targetType;
internal AnonymousClassWrapper(Type targetType, object targetInstance)
{
this.targetType = targetType;
TargetInstance = targetInstance;
}
internal AnonymousClassWrapper(SerializationInfo info, StreamingContext context)
{
var classType = (Type)info.GetValue("classType", typeof(Type));
TargetInstance = Activator.CreateInstance(classType);
foreach (FieldInfo field in classType.GetFields())
{
if (typeof(Delegate).IsAssignableFrom(field.FieldType))
//If the field is a delegate
field.SetValue(TargetInstance, ((SerializableDelegate<TDelegate>)info.GetValue(field.Name, typeof(SerializableDelegate<TDelegate>))).Delegate);
else if (!field.FieldType.IsSerializable)
//If the field is an anonymous class
field.SetValue(TargetInstance, ((AnonymousClassWrapper)info.GetValue(field.Name, typeof(AnonymousClassWrapper))).TargetInstance);
else
//otherwise
field.SetValue(TargetInstance, info.GetValue(field.Name, field.FieldType));
}
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("classType", targetType);
foreach (FieldInfo field in targetType.GetFields())
{
//See corresponding comments above
if (typeof(Delegate).IsAssignableFrom(field.FieldType))
info.AddValue(field.Name, new SerializableDelegate<TDelegate>((TDelegate)field.GetValue(TargetInstance)));
else if (!field.FieldType.IsSerializable)
info.AddValue(field.Name, new AnonymousClassWrapper(field.FieldType, field.GetValue(TargetInstance)));
else
info.AddValue(field.Name, field.GetValue(TargetInstance));
}
}
}
}
以上是关于csharp ASP.NET的助手,ASP.NET MVC应用服务器端测试的主要内容,如果未能解决你的问题,请参考以下文章