/* :: rem curl Post Json D:\curl\curl-7.33.0-win64\bin\curl.exe -i -X POST -H "Accept: application/json" -H "Content-Type: application/json; charset=utf-8" -d "[{Name:'curl1',\"Age\":0,'Height':1,'Weight':2},{'Name':\"curl2\",'Age':0,'Height':1,'Weight':2}]" "http://api.asp.net.local/services/restful/api/persons/" -v :: rem for fiddler proxy D:\curl\curl-7.33.0-win64\bin\curl.exe -i -x http://127.0.0.1:8888 -U user01:password01! -X POST -H "Accept: application/json" -H "Content-Type: application/json; charset=utf-8" -d "[{Name:'curl1',\"Age\":0,'Height':1,'Weight':2},{'Name':\"curl2\",'Age':0,'Height':1,'Weight':2}]" "http://api.asp.net.local/services/restful/api/persons/" -v */ namespace Microshaoft { using Microshaoft.WCF.Services; using Microshaoft.Web; using Microshaoft.Win32; using System; using System.Collections; using System.ComponentModel; using System.Configuration.Install; using System.Security.Principal; using System.ServiceModel.Web; using System.ServiceProcess; using System.Web.Http.SelfHost; public class WindowsServiceHost : ServiceBase { static void Main(string[] args) { Console.WriteLine(Environment.CommandLine); WindowsServiceHost service = new WindowsServiceHost(); int l = 0; bool needFreeConsole = false; if (args != null) { l = args.Length; } if (l > 0) { if (args[0].ToLower() == "/console") { needFreeConsole = true; Console.Title = "Service Run as Console ..."; Console.WriteLine("Alloc Console ..."); NativeMethods.AllocConsole(); service.OnStart(args); Console.ReadLine(); return; } } Console.WriteLine("Service"); ServiceBase.Run(service); if (needFreeConsole) { Console.WriteLine("Free Console ..."); NativeMethods.FreeConsole(); } } //public WindowsServiceHost() //{ //CanPauseAndContinue = true; //} protected override void OnStart(string[] args) { Console.WriteLine("[{0}]", string.Join(" ", args)); Console.WriteLine("Current User Identity: {0}", WindowsIdentity.GetCurrent().Name); Console.WriteLine(".Net Framework version: {0}", Environment.Version.ToString()); // MVC WebAPI Self-Host Service var config = new HttpSelfHostConfiguration("http://localhost:9080/"); MvcApiConfigHelper.Config(config); PerformanceCountersConfiguration.AttachPerformanceCounters(); HttpSelfHostServer httpSelfHostServer = new HttpSelfHostServer(config); { httpSelfHostServer.OpenAsync().Wait(); //Console.WriteLine("Press Enter to quit."); //Console.ReadLine(); } // WCF Self-Host Service WebServiceHost webServiceHost = new WebServiceHost(typeof(PersonsServices)); { webServiceHost.Open(); //Console.ReadLine(); } // Client Test ClientTest .Program .Main1 ( new string[] { @"http://api.asp.net.local/services/restful/api/Persons/" } ); ClientTest .Program .Main1 ( new string[] { @"http://localhost:9080/services/restful/api/Persons/" } ); } } [RunInstallerAttribute(true)] public class ProjectInstaller : Installer { private ServiceInstaller _serviceInstaller; private ServiceProcessInstaller _processInstaller; public ProjectInstaller() { _processInstaller = new ServiceProcessInstaller(); _serviceInstaller = new ServiceInstaller(); // Service will run under system account _processInstaller.Account = ServiceAccount.LocalSystem; // Service will have Start Type of Manual _serviceInstaller.StartType = ServiceStartMode.Manual; //_serviceInstaller.ServiceName = WindowsServiceHost.serviceName; Installers.Add(_serviceInstaller); Installers.Add(_processInstaller); } public override void Install(IDictionary stateSaver) { SetServiceName(); base.Install(stateSaver); } public override void Uninstall(IDictionary savedState) { SetServiceName(); base.Uninstall(savedState); } private void SetServiceName() { var parameters = Context.Parameters; var parametersKeys = parameters.Keys; //foreach (KeyValuePair<string, string> kvp in parameters) foreach (string s in parametersKeys) { var k = s.Trim().ToLower(); if (k == "servicename") { //var serviceName = kvp.Value; var serviceName = parameters[k]; _serviceInstaller.ServiceName = serviceName; _serviceInstaller.DisplayName = serviceName; break; } } } } } namespace Microshaoft { using System.Diagnostics; public static class PerformanceCountersConfiguration { public static void AttachPerformanceCounters() { EasyPerformanceCountersHelper<CommonPerformanceCountersContainer> .AttachPerformanceCountersCategoryInstance ( PerformanceCountersConfiguration .PerformanceCountersCategoryName , PerformanceCountersConfiguration .PerformanceCountersCategoryInstanceName ); } public static string PerformanceCountersCategoryName { get { return "Microshaoft EasyPerformanceCounters Category"; } } public static string PerformanceCountersCategoryInstanceName { get { return string.Format ( "{2}{0}{3}{1}{4}" , ": " , " @ " , Process.GetCurrentProcess().ProcessName , "" , "WebApiCountPerformanceActionFilter" ); } } public static MultiPerformanceCountersTypeFlags EnableCounters { get { return MultiPerformanceCountersTypeFlags.ProcessCounter | MultiPerformanceCountersTypeFlags.ProcessedAverageTimerCounter | MultiPerformanceCountersTypeFlags.ProcessedCounter | MultiPerformanceCountersTypeFlags.ProcessedRateOfCountsPerSecondCounter | MultiPerformanceCountersTypeFlags.ProcessingCounter; } } } } namespace Microshaoft.Win32 { using System.Runtime.InteropServices; public class NativeMethods { /// <summary> /// 启动控制台 /// </summary> /// <returns></returns> [DllImport("kernel32.dll")] public static extern bool AllocConsole(); /// <summary> /// 释放控制台 /// </summary> /// <returns></returns> [DllImport("kernel32.dll")] public static extern bool FreeConsole(); } } namespace ClientTest { using Microshaoft; using Microshaoft.Models; using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Headers; public class Program { public static void Main1(string[] args) { //@"http://api.asp.net.local/services/restful/api/Persons/"; string url = args[0]; HttpClient client = new HttpClient(); client .DefaultRequestHeaders .Accept .Add ( new MediaTypeWithQualityHeaderValue("application/json") ); Console.WriteLine("Get test:"); var result = client.GetJsonObjects<Person>(url); foreach (var i in result) { Console.WriteLine(i); } Console.WriteLine("Post test:"); HttpResponseMessage response = client.PostJsonObjects<Person> ( url , new Person[] { new Person() { Name = "c1" , Height = 1 , Weight = 2 } , new Person() { Name = "c2" , Height = 1 , Weight = 2 } } ); Console.WriteLine(response.IsSuccessStatusCode); if (response.IsSuccessStatusCode) { result = response.Content.ReadAsAsync<IEnumerable<Person>>().Result; foreach (var i in result) { Console.WriteLine(i); } } //Console.ReadLine(); } } } namespace Microshaoft { using System.Collections.Generic; using System.Net.Http; public static partial class HttpClientExtensionsMethodsManager { public static IEnumerable<T> GetJsonObjects<T>(this HttpClient httpClient, string url) { HttpResponseMessage response = httpClient.GetAsync(url).Result; var result = response.Content.ReadAsAsync<IEnumerable<T>>().Result; return result; } public static HttpResponseMessage PostJsonObjects<T> ( this HttpClient httpClient , string url , T[] jsonObjects ) { HttpResponseMessage response = httpClient.PostAsJsonAsync(url, jsonObjects).Result; return response; } } } // Models.cs namespace Microshaoft.Models { using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net.Http.Headers; using System.Runtime.Serialization; using System.Web; public static class PersonsManager { public static List<Person> _persons = new Person[] { new Person("张栢芝", 71, 178, 49) , new Person("章子怡", 23, 177, 33) , new Person("周迅", 12, 180, 80) , new Person("徐静蕾", 12, 150, 70) , new Person("赵薇", 23, 166, 60) , new Person("宋丹丹", 50, 183, 50) , new Person("翠花儿", 23, 177, 34) , new Person("赵丽蓉", 50, 184, 40) , new Person("郭晶晶", 50, 184, 41) }.ToList(); public static List<Person> Persons { get { return _persons; } } } [DataContract] public class Person : IComparable<Person> { [DataMember] public string Name { get; set; } [DataMember] public int Age { get; set; } [DataMember] public int Height { get; set; } [DataMember] public int Weight { get; set; } public Person(string name, int age, int height, int weight) { Name = name; Age = age; Height = height; Weight = weight; } public Person() { } public override string ToString() { return string.Format ( "姓名:{0}, 年龄:{1:N}, 体重:{2:N}, 身高:{3:N}" , Name , Age , Height , Weight ); } public int CompareTo(Person other) { int r = 0; r = Age - other.Age; if (r == 0) { r = Height - other.Height; if (r == 0) { r = Weight - other.Weight; } } return r; } } public class PerformanceCounterWrapper { private PerformanceCounter _performanceCounter; public PerformanceCounterWrapper() { } public PerformanceCounterWrapper(PerformanceCounter performanceCounter) { _performanceCounter = performanceCounter; } public string CategoryName { get { return _performanceCounter.CategoryName; } set { } } public string CounterName { get { return _performanceCounter.CounterName; } set { } } public string InstanceName { get { return _performanceCounter.InstanceName; } set { } } public float NextValue { get { return _performanceCounter.NextValue(); } set { } } public long RawValue { get { return _performanceCounter.RawValue; } set { } } public string CounterType { get { return Enum.GetName ( typeof(PerformanceCounterType) , _performanceCounter.CounterType ); } set { } } } public class CookieStateWrapper { private CookieState _cookieState = null; private CookieHeaderValue _cookieHeaderValue = null; public CookieStateWrapper() { } public CookieStateWrapper(CookieHeaderValue cookieHeaderValue, CookieState cookieState) { _cookieState = cookieState; _cookieHeaderValue = cookieHeaderValue; } public string Name { get { return _cookieState.Name; } set { } } public string Value { get { return _cookieState.Value; } set { } } public string Domain { get { return _cookieHeaderValue.Domain; } set { } } public string Path { get { return _cookieHeaderValue.Path; } set { } } public DateTimeOffset? Expires { get { return _cookieHeaderValue.Expires; } set { } } } public class HttpCookieWrapper { private HttpCookie _httpCookie; public HttpCookieWrapper() { } public HttpCookieWrapper(HttpCookie httpCookie) { _httpCookie = httpCookie; } public string Name { get { return _httpCookie.Name; } set { } } public string Value { get { return _httpCookie.Value; } set { } } public string Domain { get { return _httpCookie.Domain; } set { } } public string Path { get { return _httpCookie.Path; } set { } } public DateTime Expires { get { return _httpCookie.Expires; } set { } } } } // WCF.Contracts.cs namespace Microshaoft.WCF.Contracts { using Microshaoft.Models; using System.Collections.Generic; using System.ServiceModel; using System.ServiceModel.Web; [ServiceContract] public interface IPersonsServices { [OperationContract] [ WebInvoke ( Method = "GET" , BodyStyle = WebMessageBodyStyle.WrappedRequest , ResponseFormat = WebMessageFormat.Json , UriTemplate = "{name}" ) ] IEnumerable<Person> GetData(string name); } } // WCF.Services.cs namespace Microshaoft.WCF.Services { using Microshaoft.Models; using Microshaoft.WCF.Contracts; using System.Collections.Generic; using System.Linq; using System.ServiceModel.Activation; [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class PersonsServices : IPersonsServices { public IEnumerable<Person> GetData(string name) { if (name == "*") { return PersonsManager.Persons; } else { return PersonsManager.Persons.Where(x => x.Name == name).ToList(); } } } } // WebAPI.Controllers.cs namespace Microshaoft.WebApi.Controllers { using Microshaoft.Models; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Http; using System.Web; using System.Web.Http; //using System.Web.Cors; using System.Web.Http.Cors; // http://api.asp.net.local/services/restful/api/perfmon/Process/Private%20Bytes/Explorer public class PerfMonController : ApiController { [HttpGet] public PerformanceCounterWrapper Get ( [FromUri] string category, [FromUri] string counter, [FromUri] string instance ) { return new PerformanceCounterWrapper ( new PerformanceCounter ( category , counter , instance , true ) ); } } // http://api.asp.net.local/services/restful/api/cookies/* public class CookiesController : ApiController { [HttpGet] public IEnumerable<CookieStateWrapper> Get() { List<CookieStateWrapper> list = new List<CookieStateWrapper>(); //this. Request .Headers .GetCookies() .ToList() .ForEach ( (x) => { x.Cookies.ToList().ForEach ( (xx) => { list.Add ( new CookieStateWrapper(x, xx) ); } ); } ); return list; } } // http://api.asp.net.local/services/restful/api/httpcookies/* public class HttpCookiesController : ApiController { [HttpGet] public IEnumerable<HttpCookieWrapper> Get() { List<HttpCookieWrapper> list = new List<HttpCookieWrapper>(); var cookies = HttpContext.Current.Request.Cookies; var l = cookies.Count; for (int i = 0; i < l; i++) { list.Add ( new HttpCookieWrapper(cookies[i]) ); } return list; } } [EnableCors(origins: "*", headers: "*, Origin, X-Requested-With, Content-Type, Accept", methods: "*")] //[EnableCors(origins: "*", headers: "*", methods: "*")] public class PersonsController : ApiController { [HttpGet] public IEnumerable<Person> Jet(string name = "*") { if (name == "*") { return PersonsManager.Persons; } else { return PersonsManager.Persons.Where(x => x.Name == name).ToList(); } } // POST api/values //public HttpResponseMessage Post([FromBody]string value) //{ // var response = Request.CreateResponse(HttpStatusCode.Created); // return response; //} [EnableCors(origins: "*", headers: "*, Origin, X-Requested-With, Content-Type, Accept", methods: "*")] public HttpResponseMessage Post ( [FromBody] List<Person> x, [FromUri] string name = "" ) { x[0].Name = x[0].Name + name; PersonsManager.Persons.AddRange(x); //PersonsManager.Persons.Add(x); var response = Request.CreateResponse<List<Person>>(HttpStatusCode.Created, x); //var cookie = new CookieHeaderValue("customCookie", "cookieVal"); //cookie.Expires = DateTimeOffset.Now.AddDays(1); //cookie.Domain = Request.RequestUri.Host; //cookie.Path = "/"; //response.Headers.AddCookies(new CookieHeaderValue[] { cookie }); //string uri = Url.Link("DefaultApi", new { Name = item.Name }); //response.Headers.Location = new Uri(uri); return response; } /// public HttpResponseMessage Post(Person item) /// { /// PersonsManager.Persons.Add(item); /// var response = Request.CreateResponse<Person>(HttpStatusCode.Created, item); /// /// //string uri = Url.Link("DefaultApi", new { Name = item.Name }); /// //response.Headers.Location = new Uri(uri); /// return response; /// } // PUT api/values/5 public void Put(int id, [FromBody]string value) { } public void Put(int id, Person item) { PersonsManager.Persons[id] = item; } // DELETE api/values/5 public void Delete(int id) { PersonsManager.Persons.RemoveAt(id); } } } // WebAPI.BundleConfig.cs namespace Microshaoft.WebMvc { using System.Web.Optimization; public class BundleConfig { // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725 public static void RegisterBundles(BundleCollection bundles) { bundles.Add ( new ScriptBundle("~/bundles/jquery") .Include("~/Scripts/jquery-{version}.js") ); bundles.Add ( new ScriptBundle("~/bundles/jqueryui") .Include("~/Scripts/jquery-ui-{version}.js") ); bundles.Add ( new ScriptBundle("~/bundles/jqueryval") .Include ( "~/Scripts/jquery.unobtrusive*" , "~/Scripts/jquery.validate*" ) ); // Use the development version of Modernizr to develop with and learn from. Then, when you're // ready for production, use the build tool at http://modernizr.com to pick only the tests you need. bundles.Add ( new ScriptBundle("~/bundles/modernizr") .Include("~/Scripts/modernizr-*") ); bundles.Add ( new StyleBundle("~/Content/css") .Include("~/Content/site.css") ); bundles.Add ( new StyleBundle("~/Content/themes/base/css") .Include ( "~/Content/themes/base/jquery.ui.core.css", "~/Content/themes/base/jquery.ui.resizable.css", "~/Content/themes/base/jquery.ui.selectable.css", "~/Content/themes/base/jquery.ui.accordion.css", "~/Content/themes/base/jquery.ui.autocomplete.css", "~/Content/themes/base/jquery.ui.button.css", "~/Content/themes/base/jquery.ui.dialog.css", "~/Content/themes/base/jquery.ui.slider.css", "~/Content/themes/base/jquery.ui.tabs.css", "~/Content/themes/base/jquery.ui.datepicker.css", "~/Content/themes/base/jquery.ui.progressbar.css", "~/Content/themes/base/jquery.ui.theme.css" ) ); } } } // WebAPI.FilterConfig.cs namespace Microshaoft.WebMvc { using System.Web.Mvc; public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); } } } // WebAPI.RouteConfig.cs namespace Microshaoft.WebMvc { using System.Web.Mvc; using System.Web.Routing; public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute ( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } } // WebAPI.WebApiConfig.cs namespace Microshaoft.WebApi { using System.Web.Http; using System.Web.Http.Cors; public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute ( name: "DefaultApi", routeTemplate: "services/restful/api/{controller}/{name}", defaults: new { name = RouteParameter.Optional } ); config.Routes.MapHttpRoute ( name: "PerfmonApi", routeTemplate: "services/restful/api/{controller}/{category}/{counter}/{instance}", defaults: new { category = RouteParameter.Optional , counter = RouteParameter.Optional , instance = RouteParameter.Optional } ); // Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable<T> return type. // To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries. // For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712. //config.EnableQuerySupport(); // To disable tracing in your application, please comment out or remove the following line of code // For more information, refer to: http://www.asp.net/web-api config.EnableSystemDiagnosticsTracing(); var cors = new EnableCorsAttribute("*", "*, Origin, X-Requested-With, Content-Type, Accept", "*"); config.EnableCors(); //config.EnableCors(cors); //config.EnableCors(); } } } // Global.asax.cs // Global.asax /* <%@ Application Language="C#" Inherits="Microshaoft.Web.Global" %> */ namespace Microshaoft.Web { using Microshaoft; using Microshaoft.WCF.Services; using Microshaoft.WebApi; using System.ServiceModel.Activation; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Routing; // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class Global : HttpApplication { public void Application_Start() { //return; AreaRegistration.RegisterAllAreas(); var config = GlobalConfiguration.Configuration; MvcApiConfigHelper.Config(config); RouteTable.Routes.Add ( new ServiceRoute ( "services/restful/wcf/persons" , new WebServiceHostFactory() , typeof(PersonsServices) ) ); // PerformanceCounters PerformanceCountersConfiguration.AttachPerformanceCounters(); } } } namespace Microshaoft.Web { using Microshaoft.WebApi; using Microshaoft.WebMvc; using System.Web.Http; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; public static class MvcApiConfigHelper { public static void Config(HttpConfiguration httpConfiguration) { //var globalConfiguration = GlobalConfiguration.Configuration; WebApiConfig.Register(httpConfiguration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); // comment for Web API BundleConfig.RegisterBundles(BundleTable.Bundles); // CountPerformanceActionFilter httpConfiguration.Filters.Add(new CountPerformanceActionFilter()); // JsonP httpConfiguration.Formatters.Insert(0, new JsonpMediaTypeFormatter()); } } } // WebAPI.JsonpMediaTypeFormatter.cs namespace Microshaoft.WebApi { using System; using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Formatting; using System.Net.Http.Headers; using System.Threading.Tasks; /// <summary> /// Adds JSONP support to the standard <see cref="JsonMediaTypeFormatter"/>. /// </summary> public class JsonpMediaTypeFormatter : JsonMediaTypeFormatter { private readonly HttpRequestMessage request; private string callbackQueryParameter; public JsonpMediaTypeFormatter() { SupportedMediaTypes.Add(DefaultMediaType); SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript")); this.AddQueryStringMapping("format", "jsonp", DefaultMediaType); } public JsonpMediaTypeFormatter(HttpRequestMessage request) : this() { this.request = request; } public string CallbackQueryParameter { get { return callbackQueryParameter ?? "callback"; } set { callbackQueryParameter = value; } } public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType) { if (type == null) { throw new ArgumentNullException("type"); } if (request == null) { throw new ArgumentNullException("request"); } var r = new JsonpMediaTypeFormatter(request) { SerializerSettings = SerializerSettings }; return r; } public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContent content, TransportContext transportContext) { string callback; if (IsJsonpRequest(request, out callback)) { var writer = new StreamWriter(stream); writer.Write(callback + "("); writer.Flush(); return base.WriteToStreamAsync ( type , value , stream , content , transportContext ).ContinueWith ( (x) => { //TODO: Inspecting the task status and acting on that is better writer.Write(")"); writer.Flush(); } ); } else { return base.WriteToStreamAsync(type, value, stream, content, transportContext); } } private bool IsJsonpRequest(HttpRequestMessage request, out string callback) { callback = null; if (request == null || request.Method != HttpMethod.Get) { return false; } var query = request.RequestUri.ParseQueryString(); callback = query[CallbackQueryParameter]; return !string.IsNullOrEmpty(callback); } } } namespace Microshaoft.OLD { using System; using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Formatting; using System.Net.Http.Headers; using System.Threading.Tasks; using System.Web; public class JsonpMediaTypeFormatter : JsonMediaTypeFormatter { private string _callbackQueryParamter; public JsonpMediaTypeFormatter() { SupportedMediaTypes.Add(DefaultMediaType); SupportedMediaTypes.Add(new MediaTypeWithQualityHeaderValue("text/javascript")); MediaTypeMappings.Add(new UriPathExtensionMapping("jsonp", DefaultMediaType)); } public string CallbackQueryParameter { get { return _callbackQueryParamter ?? "callback"; } set { _callbackQueryParamter = value; } } public override Task WriteToStreamAsync ( Type type , object value , Stream writeStream , HttpContent content , TransportContext transportContext ) { string callback; if (IsJsonpRequest(out callback)) { return Task.Factory.StartNew ( () => { var writer = new StreamWriter(writeStream); writer.Write(callback + "("); writer.Flush(); base.WriteToStreamAsync ( type , value , writeStream , content , transportContext ).Wait(); writer.Write(")"); writer.Flush(); } ); } return base.WriteToStreamAsync(type, value, writeStream, content, transportContext); } private bool IsJsonpRequest(out string callback) { callback = null; //switch (HttpContext.Current.Request.HttpMethod) switch (HttpContext.Current.Request.HttpMethod) { case "POST": callback = HttpContext .Current .Request .Form[CallbackQueryParameter]; break; default: callback = HttpContext .Current .Request .QueryString[CallbackQueryParameter]; break; } return !string.IsNullOrEmpty(callback); } } } // WebApi.MVC.CountPerformanceActionFilter.cs namespace Microshaoft.Web { using System; using System.Diagnostics; using System.Linq; using System.Web.Http.Controllers; using System.Web.Http.Filters; //using Microshaoft.WebApplications; public class CountPerformanceActionFilter : ActionFilterAttribute { private const string Key = "__action_duration__"; private string _performanceCountersCategoryName = PerformanceCountersConfiguration .PerformanceCountersCategoryName; private string _performanceCountersCategoryInstanceName = PerformanceCountersConfiguration .PerformanceCountersCategoryInstanceName; private MultiPerformanceCountersTypeFlags _enableCounters = PerformanceCountersConfiguration .EnableCounters; public override void OnActionExecuting(HttpActionContext actionContext) { /// if (SkipLogging(actionContext)) /// { /// return; /// } Stopwatch stopwatch = EasyPerformanceCountersHelper<CommonPerformanceCountersContainer> .CountPerformanceBegin ( _enableCounters , _performanceCountersCategoryName , _performanceCountersCategoryInstanceName ); if (stopwatch != null) { actionContext.Request.Properties[Key] = stopwatch; } } public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { if (!actionExecutedContext.Request.Properties.ContainsKey(Key)) { return; } var stopwatch = actionExecutedContext .Request .Properties[Key] as Stopwatch; EasyPerformanceCountersHelper<CommonPerformanceCountersContainer> .CountPerformanceEnd ( _enableCounters , _performanceCountersCategoryName , _performanceCountersCategoryInstanceName , stopwatch ); if (stopwatch != null) { var actionName = actionExecutedContext .ActionContext .ActionDescriptor .ActionName; var controllerName = actionExecutedContext .ActionContext .ActionDescriptor .ControllerDescriptor .ControllerName; Debug.Print ( string.Format ( "[Execution of{0}- {1} took {2}.]" , controllerName , actionName , stopwatch.Elapsed ) ); stopwatch = null; } } private static bool SkipLogging(HttpActionContext actionContext) { return actionContext .ActionDescriptor .GetCustomAttributes<CountPerformanceAttribute>() .Any() || actionContext .ControllerContext .ControllerDescriptor .GetCustomAttributes<CountPerformanceAttribute>() .Any(); } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true)] public class CountPerformanceAttribute : Attribute { } } namespace TestConsoleApplication { using System; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using Microshaoft; class Program { static void Main1(string[] args) { Console.WriteLine("Begin ..."); Random r = new Random(); int sleep = 2; int iterations = 10; int maxDegreeOfParallelism = 8; // Environment.ProcessorCount; var performanceCountersCategoryName = "Microshaoft EasyPerformanceCounters Category"; var performanceCountersCategoryInstanceName = string.Format ( "{2}{0}{3}{1}{4}" , ": " , " @ " , "" , "" , Process.GetCurrentProcess().ProcessName ); //EasyPerformanceCountersHelper 调用示例 EasyPerformanceCountersHelper<CommonPerformanceCountersContainer> .AttachPerformanceCountersCategoryInstance ( performanceCountersCategoryName , performanceCountersCategoryInstanceName + "-1" ); EasyPerformanceCountersHelper<CommonPerformanceCountersContainer> .AttachPerformanceCountersCategoryInstance ( performanceCountersCategoryName , performanceCountersCategoryInstanceName + "-2" ); var enableCounters = MultiPerformanceCountersTypeFlags.ProcessCounter | MultiPerformanceCountersTypeFlags.ProcessedAverageTimerCounter | MultiPerformanceCountersTypeFlags.ProcessedCounter | MultiPerformanceCountersTypeFlags.ProcessedRateOfCountsPerSecondCounter | MultiPerformanceCountersTypeFlags.ProcessingCounter; Parallel.For ( 0 , iterations , new ParallelOptions() { MaxDegreeOfParallelism = maxDegreeOfParallelism } , (x) => { EasyPerformanceCountersHelper<CommonPerformanceCountersContainer> .CountPerformance ( enableCounters , performanceCountersCategoryName , performanceCountersCategoryInstanceName + "-1" , null , () => { sleep = r.Next(0, 5) * 1000; //Thread.Sleep(sleep); throw new Exception("sadsad"); } , null , (xx) => { //Console.WriteLine("Exception {0}", xx.ToString()); return false; } , null ); } ); Parallel.For ( 0 , iterations , new ParallelOptions() { MaxDegreeOfParallelism = maxDegreeOfParallelism } , (x) => { Stopwatch stopwatch = null; try { stopwatch = EasyPerformanceCountersHelper<CommonPerformanceCountersContainer> .CountPerformanceBegin ( enableCounters , performanceCountersCategoryName , performanceCountersCategoryInstanceName + "-2" ); sleep = r.Next(0, 5) * 1000; //Thread.Sleep(sleep); throw new Exception("Test"); } catch { } finally { EasyPerformanceCountersHelper<CommonPerformanceCountersContainer> .CountPerformanceEnd ( enableCounters , performanceCountersCategoryName , performanceCountersCategoryInstanceName + "-2" , stopwatch ); } } ); Console.WriteLine("End ..."); Console.ReadLine(); } } } namespace Microshaoft { using System; using System.Collections.Generic; using System.Diagnostics; //using System.Collections.Concurrent; public static class EasyPerformanceCountersHelper<TPerformanceCountersContainer> where TPerformanceCountersContainer : class, IPerformanceCountersContainer, new () { private static Dictionary<string, TPerformanceCountersContainer> _dictionary = new Dictionary<string, TPerformanceCountersContainer>(); public static void AttachPerformanceCountersCategoryInstance ( string performanceCountersCategoryName , string performanceCountersCategoryInstanceName ) { string key = string.Format ( "{1}{0}{2}" , "-" , performanceCountersCategoryName , performanceCountersCategoryInstanceName ); TPerformanceCountersContainer container = null; if (!_dictionary.TryGetValue(key, out container)) { container = new TPerformanceCountersContainer(); _dictionary.Add ( key , container ); container .AttachPerformanceCountersToProperties ( performanceCountersCategoryInstanceName , performanceCountersCategoryName ); } } private static object _lockerObject = new object(); public static Stopwatch CountPerformanceBegin ( MultiPerformanceCountersTypeFlags enabledPerformanceCounters , string performanceCountersCategoryName , string performanceCountersCategoryInstanceName ) { Stopwatch r = null; if (enabledPerformanceCounters != MultiPerformanceCountersTypeFlags.None) { string key = string.Format ( "{1}{0}{2}" , "-" , performanceCountersCategoryName , performanceCountersCategoryInstanceName ); TPerformanceCountersContainer container = null; if (!_dictionary.TryGetValue(key, out container)) { lock (_lockerObject) { container = new TPerformanceCountersContainer(); _dictionary.Add ( key , container ); container.AttachPerformanceCountersToProperties ( performanceCountersCategoryInstanceName , performanceCountersCategoryName ); } } var enableProcessCounter = ( ( enabledPerformanceCounters & MultiPerformanceCountersTypeFlags.ProcessCounter ) != MultiPerformanceCountersTypeFlags.None ); if (enableProcessCounter) { container.PrcocessPerformanceCounter.Increment(); } var enableProcessingCounter = ( ( enabledPerformanceCounters & MultiPerformanceCountersTypeFlags.ProcessingCounter ) != MultiPerformanceCountersTypeFlags.None ); if (enableProcessingCounter) { container.ProcessingPerformanceCounter.Increment(); } var enableProcessedAverageTimerCounter = ( ( enabledPerformanceCounters & MultiPerformanceCountersTypeFlags.ProcessedAverageTimerCounter ) != MultiPerformanceCountersTypeFlags.None ); if (enableProcessedAverageTimerCounter) { r = Stopwatch.StartNew(); } } return r; } public static void CountPerformanceEnd ( MultiPerformanceCountersTypeFlags enabledPerformanceCounters , string performanceCountersCategoryName , string performanceCountersCategoryInstanceName , Stopwatch stopwatch ) { string key = string.Format ( "{1}{0}{2}" , "-" , performanceCountersCategoryName , performanceCountersCategoryInstanceName ); TPerformanceCountersContainer container = null; if (!_dictionary.TryGetValue(key, out container)) { return; } var enableProcessedAverageTimerCounter = ( ( enabledPerformanceCounters & MultiPerformanceCountersTypeFlags.ProcessedAverageTimerCounter ) != MultiPerformanceCountersTypeFlags.None ); if (enableProcessedAverageTimerCounter) { if (stopwatch != null) { PerformanceCounter performanceCounter = container.ProcessedAverageTimerPerformanceCounter; PerformanceCounter basePerformanceCounter = container.ProcessedAverageBasePerformanceCounter; stopwatch.Stop(); performanceCounter.IncrementBy(stopwatch.ElapsedTicks); basePerformanceCounter.Increment(); //stopwatch = null; } } var enableProcessingCounter = ( ( enabledPerformanceCounters & MultiPerformanceCountersTypeFlags.ProcessingCounter ) != MultiPerformanceCountersTypeFlags.None ); if (enableProcessingCounter) { container.ProcessingPerformanceCounter.Decrement(); } var enableProcessedPerformanceCounter = ( ( enabledPerformanceCounters & MultiPerformanceCountersTypeFlags.ProcessedCounter ) != MultiPerformanceCountersTypeFlags.None ); if (enableProcessedPerformanceCounter) { container.ProcessedPerformanceCounter.Increment(); } var enableProcessedRateOfCountsPerSecondPerformanceCounter = ( ( enabledPerformanceCounters & MultiPerformanceCountersTypeFlags.ProcessedRateOfCountsPerSecondCounter ) != MultiPerformanceCountersTypeFlags.None ); if (enableProcessedRateOfCountsPerSecondPerformanceCounter) { container.ProcessedRateOfCountsPerSecondPerformanceCounter.Increment(); } } public static void CountPerformance ( MultiPerformanceCountersTypeFlags enabledPerformanceCounters , string performanceCountersCategoryName , string performanceCountersCategoryInstanceName , Action onBeforeCountPerformanceInnerProcessAction , Action onCountPerformanceInnerProcessAction , Action onAfterCountPerformanceInnerProcessAction , Func<Exception, bool> onCaughtExceptionProcessFunc , Action<bool, Exception> onFinallyProcessAction ) { if (enabledPerformanceCounters != MultiPerformanceCountersTypeFlags.None) { if (onCountPerformanceInnerProcessAction != null) { string key = string.Format ( "{1}{0}{2}" , "-" , performanceCountersCategoryName , performanceCountersCategoryInstanceName ); TPerformanceCountersContainer container = null; if (!_dictionary.TryGetValue(key, out container)) { lock (_lockerObject) { container = new TPerformanceCountersContainer(); _dictionary.Add ( key , container ); container.AttachPerformanceCountersToProperties ( performanceCountersCategoryInstanceName , performanceCountersCategoryName ); } } var enableProcessCounter = ( ( enabledPerformanceCounters & MultiPerformanceCountersTypeFlags.ProcessCounter ) != MultiPerformanceCountersTypeFlags.None ); if (enableProcessCounter) { container.PrcocessPerformanceCounter.Increment(); } var enableProcessingCounter = ( ( enabledPerformanceCounters & MultiPerformanceCountersTypeFlags.ProcessingCounter ) != MultiPerformanceCountersTypeFlags.None ); if (enableProcessingCounter) { container.ProcessingPerformanceCounter.Increment(); } var enableProcessedAverageTimerCounter = ( ( enabledPerformanceCounters & MultiPerformanceCountersTypeFlags.ProcessedAverageTimerCounter ) != MultiPerformanceCountersTypeFlags.None ); var reThrowException = false; container .ProcessedAverageTimerPerformanceCounter .ChangeAverageTimerCounterValueWithTryCatchExceptionFinally ( enableProcessedAverageTimerCounter , container.ProcessedAverageBasePerformanceCounter , () => { if (onCountPerformanceInnerProcessAction != null) { if (onBeforeCountPerformanceInnerProcessAction != null) { onBeforeCountPerformanceInnerProcessAction(); } onCountPerformanceInnerProcessAction(); if (onAfterCountPerformanceInnerProcessAction != null) { onAfterCountPerformanceInnerProcessAction(); } } } , (x, y) => //catch { container .CaughtExceptionsPerformanceCounter .Increment(); var r = reThrowException; if (onCaughtExceptionProcessFunc != null) { r = onCaughtExceptionProcessFunc(y); } return r; } , (x, y, z, w) => //Finally { if (enableProcessingCounter) { container.ProcessingPerformanceCounter.Decrement(); } var enableProcessedPerformanceCounter = ( ( enabledPerformanceCounters & MultiPerformanceCountersTypeFlags.ProcessedCounter ) != MultiPerformanceCountersTypeFlags.None ); if (enableProcessedPerformanceCounter) { container.ProcessedPerformanceCounter.Increment(); } var enableProcessedRateOfCountsPerSecondPerformanceCounter = ( ( enabledPerformanceCounters & MultiPerformanceCountersTypeFlags.ProcessedRateOfCountsPerSecondCounter ) != MultiPerformanceCountersTypeFlags.None ); if (enableProcessedRateOfCountsPerSecondPerformanceCounter) { container .ProcessedRateOfCountsPerSecondPerformanceCounter .Increment(); } } ); } } else { if (onCountPerformanceInnerProcessAction != null) { onCountPerformanceInnerProcessAction(); } } } } } namespace Microshaoft { using System.Diagnostics; public interface IPerformanceCountersContainer { PerformanceCounter CaughtExceptionsPerformanceCounter { get; } PerformanceCounter PrcocessPerformanceCounter { get; } PerformanceCounter ProcessingPerformanceCounter { get; } PerformanceCounter ProcessedPerformanceCounter { get; } PerformanceCounter ProcessedRateOfCountsPerSecondPerformanceCounter { get; } PerformanceCounter ProcessedAverageTimerPerformanceCounter { get; } PerformanceCounter ProcessedAverageBasePerformanceCounter { get; } void AttachPerformanceCountersToProperties ( string instanceName , string categoryName ); } } namespace Microshaoft { using System; using System.Diagnostics; public class CommonPerformanceCountersContainer : IPerformanceCountersContainer { #region PerformanceCounters private PerformanceCounter _caughtExceptionsPerformanceCounter; [ PerformanceCounterDefinitionAttribute ( CounterType = PerformanceCounterType.NumberOfItems64 , CounterName = "99.捕获异常次数(次)" ) ] public PerformanceCounter CaughtExceptionsPerformanceCounter { private set { ReaderWriterLockSlimHelper .TryEnterWriterLockSlimWrite<PerformanceCounter> ( ref _caughtExceptionsPerformanceCounter , value , 2 ); } get { return _caughtExceptionsPerformanceCounter; } } private PerformanceCounter _processPerformanceCounter; [ PerformanceCounterDefinitionAttribute ( CounterType = PerformanceCounterType.NumberOfItems64 , CounterName = "01.接收处理笔数(笔)" ) ] public PerformanceCounter PrcocessPerformanceCounter { private set { ReaderWriterLockSlimHelper .TryEnterWriterLockSlimWrite<PerformanceCounter> ( ref _processPerformanceCounter , value , 2 ); } get { return _processPerformanceCounter; } } private PerformanceCounter _processingPerformanceCounter; [ PerformanceCounterDefinitionAttribute ( CounterType = PerformanceCounterType.NumberOfItems64 , CounterName = "02.正在处理笔数(笔)" ) ] public PerformanceCounter ProcessingPerformanceCounter { private set { ReaderWriterLockSlimHelper .TryEnterWriterLockSlimWrite<PerformanceCounter> ( ref _processingPerformanceCounter , value , 2 ); } get { return _processingPerformanceCounter; } } private PerformanceCounter _processedPerformanceCounter; [ PerformanceCounterDefinitionAttribute ( CounterType = PerformanceCounterType.NumberOfItems64 , CounterName = "03.完成处理笔数(笔)" ) ] public PerformanceCounter ProcessedPerformanceCounter { private set { ReaderWriterLockSlimHelper .TryEnterWriterLockSlimWrite<PerformanceCounter> ( ref _processedPerformanceCounter , value , 2 ); } get { return _processedPerformanceCounter; } } private PerformanceCounter _processedRateOfCountsPerSecondPerformanceCounter; [ PerformanceCounterDefinitionAttribute ( CounterType = PerformanceCounterType.RateOfCountsPerSecond64 , CounterName = "04.每秒完成处理笔数(笔/秒)" ) ] public PerformanceCounter ProcessedRateOfCountsPerSecondPerformanceCounter { private set { ReaderWriterLockSlimHelper .TryEnterWriterLockSlimWrite<PerformanceCounter> ( ref _processedRateOfCountsPerSecondPerformanceCounter , value , 2 ); } get { return _processedRateOfCountsPerSecondPerformanceCounter; } } private PerformanceCounter _ProcessedAverageTimerPerformanceCounter; [ PerformanceCounterDefinitionAttribute ( CounterType = PerformanceCounterType.AverageTimer32 , CounterName = "05.平均每笔处理耗时秒数(秒/笔)" ) ] public PerformanceCounter ProcessedAverageTimerPerformanceCounter { private set { ReaderWriterLockSlimHelper .TryEnterWriterLockSlimWrite<PerformanceCounter> ( ref _ProcessedAverageTimerPerformanceCounter , value , 2 ); } get { return _ProcessedAverageTimerPerformanceCounter; } } private PerformanceCounter _processedAverageBasePerformanceCounter; [ PerformanceCounterDefinitionAttribute ( CounterType = PerformanceCounterType.AverageBase ) ] public PerformanceCounter ProcessedAverageBasePerformanceCounter { private set { ReaderWriterLockSlimHelper .TryEnterWriterLockSlimWrite<PerformanceCounter> ( ref _processedAverageBasePerformanceCounter , value , 2 ); } get { return _processedAverageBasePerformanceCounter; } } #endregion // indexer declaration public PerformanceCounter this[string name] { get { throw new NotImplementedException(); //return null; } } //private bool _isAttachedPerformanceCounters = false; public void AttachPerformanceCountersToProperties ( string instanceName , string categoryName ) { var type = this.GetType(); PerformanceCountersHelper .AttachPerformanceCountersToProperties<CommonPerformanceCountersContainer> ( instanceName , categoryName , this ); } } } //========================================================================================= //========================================================================================= namespace Microshaoft { using System; using System.Diagnostics; public static class PerformanceCounterExtensionMethodsManager { public static void ChangeAverageTimerCounterValueWithTryCatchExceptionFinally ( this PerformanceCounter performanceCounter , bool enabled , PerformanceCounter basePerformanceCounter , Action onCountPerformanceInnerProcessAction //= null , Func<PerformanceCounter, Exception, bool> onCaughtExceptionProcessFunc //= null , Action<PerformanceCounter, PerformanceCounter, bool, Exception> onFinallyProcessAction //= null ) { if (enabled) { var stopwatch = Stopwatch.StartNew(); if (onCountPerformanceInnerProcessAction != null) { bool reThrowException = false; TryCatchFinallyProcessHelper .TryProcessCatchFinally ( true , () => { onCountPerformanceInnerProcessAction(); } , reThrowException , (x) => { var r = reThrowException; if (onCaughtExceptionProcessFunc != null) { r = onCaughtExceptionProcessFunc(performanceCounter, x); } return r; } , (x, y) => { stopwatch.Stop(); performanceCounter.IncrementBy(stopwatch.ElapsedTicks); stopwatch = null; basePerformanceCounter.Increment(); if (onFinallyProcessAction != null) { onFinallyProcessAction ( performanceCounter , basePerformanceCounter , x , y ); } } ); } } } } } namespace Microshaoft { using System; using System.Diagnostics; [FlagsAttribute] public enum MultiPerformanceCountersTypeFlags : ushort { None = 0, ProcessCounter = 1, ProcessingCounter = 2, ProcessedCounter = 4, ProcessedAverageTimerCounter = 8, ProcessedRateOfCountsPerSecondCounter = 16 }; [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public class PerformanceCounterDefinitionAttribute : Attribute { public PerformanceCounterType CounterType; public string CounterName; } } namespace Microshaoft { using System.Diagnostics; using System.Linq; public static class PerformanceCountersHelper { public static void AttachPerformanceCountersToProperties<T> ( string performanceCounterInstanceName , string category , T target //= default(T) ) { var type = typeof(T); var propertiesList = type.GetProperties().ToList(); propertiesList = propertiesList.Where ( (pi) => { var parameters = pi.GetIndexParameters(); return ( pi.PropertyType == typeof(PerformanceCounter) && (parameters == null ? 0 : parameters.Length) <= 0 ); } ).ToList(); if (PerformanceCounterCategory.Exists(category)) { propertiesList.ForEach ( (pi) => { if (PerformanceCounterCategory.CounterExists(pi.Name, category)) { if (PerformanceCounterCategory.InstanceExists(performanceCounterInstanceName, category)) { //var pc = new PerformanceCounter(category, pi.Name, instanceName, false); //pc.InstanceName = instanceName; //pc.RemoveInstance(); } } } ); //PerformanceCounterCategory.Delete(category); } if (!PerformanceCounterCategory.Exists(category)) { var ccdc = new CounterCreationDataCollection(); propertiesList.ForEach ( (pi) => { var propertyName = pi.Name; var performanceCounterType = PerformanceCounterType.NumberOfItems64; var performanceCounterName = propertyName; var attribute = pi.GetCustomAttributes(false).FirstOrDefault ( (x) => { return x as PerformanceCounterDefinitionAttribute != null; } ) as PerformanceCounterDefinitionAttribute; if (attribute != null) { var counterName = attribute.CounterName; if (!string.IsNullOrEmpty(counterName)) { performanceCounterName = counterName; } var counterType = attribute.CounterType; //if (counterType != null) { performanceCounterType = counterType; } } var ccd = PerformanceCountersHelper .GetCounterCreationData ( performanceCounterName , performanceCounterType ); ccdc.Add(ccd); } ); PerformanceCounterCategory.Create ( category, string.Format("{0} Category Help.", category), PerformanceCounterCategoryType.MultiInstance, ccdc ); } propertiesList.ForEach ( (pi) => { var propertyName = pi.Name; var performanceCounterType = PerformanceCounterType.NumberOfItems64; var performanceCounterName = propertyName; var attribute = pi .GetCustomAttributes(false) .FirstOrDefault ( (x) => { return ( (x as PerformanceCounterDefinitionAttribute) != null ); } ) as PerformanceCounterDefinitionAttribute; if (attribute != null) { var counterName = attribute.CounterName; if (!string.IsNullOrEmpty(counterName)) { performanceCounterName = counterName; } var counterType = attribute.CounterType; //if (counterType != null) { performanceCounterType = counterType; } } var pc = new PerformanceCounter() { CategoryName = category , CounterName = performanceCounterName , InstanceLifetime = PerformanceCounterInstanceLifetime.Process , InstanceName = performanceCounterInstanceName , ReadOnly = false , RawValue = 0 }; if (pi.GetGetMethod().IsStatic) { var setter = DynamicPropertyAccessor .CreateSetStaticPropertyValueAction<PerformanceCounter> ( type , propertyName ); setter(pc); } else { if (target != null) { var setter = DynamicPropertyAccessor .CreateSetPropertyValueAction<PerformanceCounter> ( type , propertyName ); setter(target, pc); } } } ); } public static CounterCreationData GetCounterCreationData ( string counterName , PerformanceCounterType performanceCounterType ) { return new CounterCreationData() { CounterName = counterName , CounterHelp = string.Format("{0} Help", counterName) , CounterType = performanceCounterType }; } } } namespace Microshaoft { using System; using System.Threading; public static class ReaderWriterLockSlimHelper { public static bool TryEnterWriterLockSlimWrite<T> ( ref T target , T newValue , int enterTimeOutSeconds ) where T : class { bool r = false; var rwls = new ReaderWriterLockSlim(); int timeOut = Timeout.Infinite; if (enterTimeOutSeconds >= 0) { timeOut = enterTimeOutSeconds * 1000; } try { r = (rwls.TryEnterWriteLock(timeOut)); if (r) { Interlocked.Exchange<T>(ref target, newValue); r = true; } } finally { if (r) { rwls.ExitWriteLock(); } } return r; } public static bool TryEnterWriterLockSlim ( Action action , int enterTimeOutSeconds ) { bool r = false; if (action != null) { var rwls = new ReaderWriterLockSlim(); int timeOut = Timeout.Infinite; if (enterTimeOutSeconds >= 0) { timeOut = enterTimeOutSeconds * 1000; } try { r = (rwls.TryEnterWriteLock(timeOut)); if (r) { action(); r = true; } } finally { if (r) { rwls.ExitWriteLock(); } } } return r; } } } namespace Microshaoft { using System; using System.Linq; using System.Linq.Expressions; using System.Reflection; public class DynamicPropertyAccessor { private static Assembly GetAssemblyByTypeName(string typeName) { return AppDomain .CurrentDomain .GetAssemblies() .First ( (a) => { return a .GetTypes() .Any ( (t) => { return ( t.FullName == typeName ); } ); } ); } public static Func<object, object> CreateGetPropertyValueFunc ( string typeName , string propertyName , bool isTypeFromAssembly = false ) { Type type; if (isTypeFromAssembly) { var assembly = GetAssemblyByTypeName(typeName); type = assembly.GetType(typeName); } else { type = Type.GetType(typeName); } return CreateGetPropertyValueFunc(type, propertyName); } public static Func<object, object> CreateGetPropertyValueFunc ( Type type , string propertyName ) { var target = Expression.Parameter(typeof(object)); var castTarget = Expression.Convert(target, type); var getPropertyValue = Expression.Property(castTarget, propertyName); var castPropertyValue = Expression.Convert(getPropertyValue, typeof(object)); var lambda = Expression.Lambda<Func<object, object>>(castPropertyValue, target); return lambda.Compile(); } public static Func<object, TProperty> CreateGetPropertyValueFunc<TProperty> ( string typeName , string propertyName , bool isTypeFromAssembly = false ) { Type type; if (isTypeFromAssembly) { var assembly = GetAssemblyByTypeName(typeName); type = assembly.GetType(typeName); } else { type = Type.GetType(typeName); } return CreateGetPropertyValueFunc<TProperty>(type, propertyName); } public static Func<object, TProperty> CreateGetPropertyValueFunc<TProperty> ( Type type , string propertyName ) { var target = Expression.Parameter(typeof(object)); var castTarget = Expression.Convert(target, type); var getPropertyValue = Expression.Property(castTarget, propertyName); var lambda = Expression.Lambda<Func<object, TProperty>>(getPropertyValue, target); return lambda.Compile(); } public static Func<TProperty> CreateGetStaticPropertyValueFunc<TProperty> ( string typeName , string propertyName , bool isTypeFromAssembly = false ) { Type type; if (isTypeFromAssembly) { var assembly = GetAssemblyByTypeName(typeName); type = assembly.GetType(typeName); } else { type = Type.GetType(typeName); } return CreateGetStaticPropertyValueFunc<TProperty>(type, propertyName); } public static Func<TProperty> CreateGetStaticPropertyValueFunc<TProperty> ( Type type , string propertyName ) { Func<TProperty> func = null; var property = type.GetProperty(propertyName, typeof(TProperty)); if (property == null) { property = type .GetProperties() .ToList() .FirstOrDefault ( (x) => { return ( x.Name.ToLower() == propertyName.ToLower() ); } ); } if (property != null) { var getPropertyValue = Expression.Property(null, property); var lambda = Expression.Lambda<Func<TProperty>>(getPropertyValue, null); func = lambda.Compile(); } return func; } public static Func<object> CreateGetStaticPropertyValueFunc ( Type type , string propertyName ) { Func<object> func = null; var property = type.GetProperty(propertyName); if (property == null) { property = type .GetProperties() .ToList() .FirstOrDefault ( (x) => { return ( x.Name.ToLower() == propertyName.ToLower() ); } ); } if (property != null) { var getPropertyValue = Expression.Property(null, property); var castPropertyValue = Expression.Convert(getPropertyValue, typeof(object)); var lambda = Expression.Lambda<Func<object>>(castPropertyValue, null); func = lambda.Compile(); } return func; } public static Func<object> CreateGetStaticPropertyValueFunc ( string typeName , string propertyName , bool isTypeFromAssembly = false ) { Type type; if (isTypeFromAssembly) { var assembly = GetAssemblyByTypeName(typeName); type = assembly.GetType(typeName); } else { type = Type.GetType(typeName); } return CreateGetStaticPropertyValueFunc(type, propertyName); } public static Action<object, object> CreateSetPropertyValueAction ( Type type , string propertyName ) { Action<object, object> action = null; var property = type.GetProperty(propertyName); if (property == null) { property = type .GetProperties() .ToList() .FirstOrDefault ( (x) => { return ( x.Name.ToLower() == propertyName.ToLower() ); } ); } if (property != null) { var target = Expression.Parameter(typeof(object)); var propertyValue = Expression.Parameter(typeof(object)); var castTarget = Expression.Convert(target, type); var castPropertyValue = Expression.Convert(propertyValue, property.PropertyType); var getSetMethod = property.GetSetMethod(); if (getSetMethod == null) { getSetMethod = property.GetSetMethod(true); } var call = Expression.Call(castTarget, getSetMethod, castPropertyValue); var lambda = Expression.Lambda<Action<object, object>>(call, target, propertyValue); action = lambda.Compile(); } return action; } public static Action<object, object> CreateSetPropertyValueAction ( string typeName , string propertyName , bool isTypeFromAssembly = false ) { Type type; if (isTypeFromAssembly) { var assembly = GetAssemblyByTypeName(typeName); type = assembly.GetType(typeName); } else { type = Type.GetType(typeName); } return CreateSetPropertyValueAction(type, propertyName); } public static Action<object, TProperty> CreateSetPropertyValueAction<TProperty> ( Type type , string propertyName ) { Action<object, TProperty> action = null; var property = type.GetProperty(propertyName); if (property == null) { property = type .GetProperties() .ToList() .FirstOrDefault ( (x) => { return ( x.Name.ToLower() == propertyName.ToLower() ); } ); } if (property != null) { var target = Expression.Parameter(typeof(object)); var propertyValue = Expression.Parameter(typeof(TProperty)); var castTarget = Expression.Convert(target, type); var castPropertyValue = Expression.Convert(propertyValue, property.PropertyType); var getSetMethod = property.GetSetMethod(); if (getSetMethod == null) { getSetMethod = property.GetSetMethod(true); } var call = Expression.Call(castTarget, getSetMethod, castPropertyValue); var lambda = Expression.Lambda<Action<object, TProperty>>(call, target, propertyValue); action = lambda.Compile(); } return action; } public static Action<object, TProperty> CreateSetPropertyValueAction<TProperty> ( string typeName , string propertyName , bool isTypeFromAssembly = false ) { Type type; if (isTypeFromAssembly) { var assembly = GetAssemblyByTypeName(typeName); type = assembly.GetType(typeName); } else { type = Type.GetType(typeName); } return CreateSetPropertyValueAction<TProperty>(type, propertyName); } public static Action<object> CreateSetStaticPropertyValueAction ( Type type , string propertyName ) { Action<object> action = null; var property = type.GetProperty(propertyName); if (property == null) { property = type .GetProperties() .ToList() .FirstOrDefault ( (x) => { return ( x.Name.ToLower() == propertyName.ToLower() ); } ); } if (property != null) { var propertyValue = Expression.Parameter(typeof(object)); var castPropertyValue = Expression.Convert(propertyValue, property.PropertyType); var getSetMethod = property.GetSetMethod(); if (getSetMethod == null) { getSetMethod = property.GetSetMethod(true); } var call = Expression.Call(null, getSetMethod, castPropertyValue); var lambda = Expression.Lambda<Action<object>>(call, propertyValue); action = lambda.Compile(); } return action; } public static Action<object> CreateSetStaticPropertyValueAction ( string typeName , string propertyName , bool isTypeFromAssembly = false ) { Type type; if (isTypeFromAssembly) { var assembly = GetAssemblyByTypeName(typeName); type = assembly.GetType(typeName); } else { type = Type.GetType(typeName); } return CreateSetStaticPropertyValueAction(type, propertyName); } public static Action<TProperty> CreateSetStaticPropertyValueAction<TProperty> ( Type type , string propertyName ) { Action<TProperty> action = null; var property = type.GetProperty(propertyName); if (property == null) { property = type .GetProperties() .ToList() .FirstOrDefault ( (x) => { return ( x.Name.ToLower() == propertyName.ToLower() ); } ); } if (property != null) { var propertyValue = Expression.Parameter(typeof(TProperty)); //var castPropertyValue = Expression.Convert(propertyValue, property.PropertyType); var getSetMethod = property.GetSetMethod(); if (getSetMethod == null) { getSetMethod = property.GetSetMethod(true); } var call = Expression.Call(null, getSetMethod, propertyValue); var lambda = Expression.Lambda<Action<TProperty>>(call, propertyValue); action = lambda.Compile(); } return action; } public static Action<TProperty> CreateSetStaticPropertyValueAction<TProperty> ( string typeName , string propertyName , bool isTypeFromAssembly = false ) { Type type; if (isTypeFromAssembly) { var assembly = GetAssemblyByTypeName(typeName); type = assembly.GetType(typeName); } else { type = Type.GetType(typeName); } return CreateSetStaticPropertyValueAction<TProperty>(type, propertyName); } } } namespace Microshaoft { using System; using System.Diagnostics; using System.Reflection; using System.Threading.Tasks; public static class TryCatchFinallyProcessHelper { public static async Task<T> TryProcessCatchFinallyAsync<T> ( bool needTry , Func<Task<T>> onTryProcessFunc , bool reThrowException = false , Func<Exception, bool> onCaughtExceptionProcessFunc = null , Action<bool, Exception> onFinallyProcessAction = null ) { T r = default(T); //if (onTryProcessAction != null) { if (needTry) { Exception exception = null; var caughtException = false; try { r = await onTryProcessFunc(); return r; } catch (Exception e) { caughtException = true; exception = e; var currentCalleeMethod = MethodInfo.GetCurrentMethod(); var currentCalleeType = currentCalleeMethod.DeclaringType; StackTrace stackTrace = new StackTrace(); StackFrame stackFrame = stackTrace.GetFrame(1); var callerMethod = stackFrame.GetMethod(); var callerType = callerMethod.DeclaringType; var frame = (stackTrace.FrameCount > 1 ? stackTrace.FrameCount - 1 : 1); stackFrame = stackTrace.GetFrame(frame); var originalCallerMethod = stackFrame.GetMethod(); var originalCallerType = originalCallerMethod.DeclaringType; var innerExceptionMessage = string.Format ( "Rethrow caught [{1}] Exception{0} at Callee Method: [{2}]{0} at Caller Method: [{3}]{0} at Original Caller Method: [{4}]" , "\r\n\t" , e.Message , string.Format("{1}{0}{2}", "::", currentCalleeType, currentCalleeMethod) , string.Format("{1}{0}{2}", "::", callerType, callerMethod) , string.Format("{1}{0}{2}", "::", originalCallerType, originalCallerMethod) ); Console.WriteLine(innerExceptionMessage); if (onCaughtExceptionProcessFunc != null) { reThrowException = onCaughtExceptionProcessFunc(e); } if (reThrowException) { throw new Exception ( innerExceptionMessage , e ); } return r; } finally { if (onFinallyProcessAction != null) { onFinallyProcessAction(caughtException, exception); } } } else { return await onTryProcessFunc(); } } } public static void TryProcessCatchFinally ( bool needTry , Action onTryProcessAction , bool reThrowException = false , Func<Exception, bool> onCaughtExceptionProcessFunc = null , Action<bool, Exception> onFinallyProcessAction = null ) { if (onTryProcessAction != null) { if (needTry) { Exception exception = null; var caughtException = false; try { onTryProcessAction(); } catch (Exception e) { caughtException = true; exception = e; var currentCalleeMethod = MethodInfo.GetCurrentMethod(); var currentCalleeType = currentCalleeMethod.DeclaringType; StackTrace stackTrace = new StackTrace(e, true); StackFrame stackFrame = stackTrace.GetFrame(1); var callerMethod = stackFrame.GetMethod(); var callerType = callerMethod.DeclaringType; var frame = (stackTrace.FrameCount > 1 ? stackTrace.FrameCount - 1 : 1); stackFrame = stackTrace.GetFrame(frame); var originalCallerMethod = stackFrame.GetMethod(); var originalCallerType = originalCallerMethod.DeclaringType; var innerExceptionMessage = string.Format ( "Rethrow caught [{1}] Exception{0} at Callee Method: [{2}]{0} at Caller Method: [{3}]{0} at Original Caller Method: [{4}]" , "\r\n\t" , e.Message , string.Format("{1}{0}{2}", "::", currentCalleeType, currentCalleeMethod) , string.Format("{1}{0}{2}", "::", callerType, callerMethod) , string.Format("{1}{0}{2}", "::", originalCallerType, originalCallerMethod) ); //Console.WriteLine(innerExceptionMessage); if (onCaughtExceptionProcessFunc != null) { reThrowException = onCaughtExceptionProcessFunc(e); } if (reThrowException) { throw new Exception ( innerExceptionMessage , e ); } } finally { //Console.WriteLine("Finally"); if (onFinallyProcessAction != null) { onFinallyProcessAction(caughtException, exception); } } } else { onTryProcessAction(); } } } } } // .html /* <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Microshaoft Cross-Domain + ASP.NET MVC 4 WebAPI + JsonpMediaTypeFormatter + Knockout.js + MVVM Sample</title> <!-- <base href="http://api.asp.net.local" /> --> <!-- <script src="http://api.asp.net.local/Scripts/jquery.mobile-1.3.1.js" type="text/javascript"></script> --> <script src="http://scripts.asp.net.local/Scripts/jquery-2.0.3.js" type="text/javascript"></script> <script src="http://scripts.asp.net.local/Scripts/knockout-2.3.0.js" type="text/javascript"></script> <script src="http://scripts.asp.net.local/Scripts/knockout.simpleGrid.1.3.js" type="text/javascript"></script> </head> <body> <input type="button" value="Load from IIS+WebAPI+JsonP+Cross-Domain" onclick="GetData('http://api.asp.net.local/services/restful/api/persons/*?callback=?');" /> <br /> <input type="button" value="Load from WebAPI Self-Host+JsonP+Cross-Domain" onclick="GetData('http://localhost:9080/services/restful/api/persons/*?callback=?');" /> <br /> <input type="button" value="Load from Console+WCF+JsonP+Cross-Domain" onclick="GetData('http://api.asp.net.local:1080/services/restful/wcf/persons/*?callback=?');" /> <br /> <input type="button" value="Load from IIS+WCF+Json" onclick="GetData('http://portal.asp.net.local/services/restful/wcf/persons/*');" /> <br /> <input type="button" value="Load from WebAPI Self-Host+Json" onclick="GetData('http://localhost:9080/services/restful/api/persons/*');" /> <br /> <div> <div data-bind='simpleGrid: gridViewModel'> PlaceHolder </div> <button data-bind='click: sortByPriceDesc'> Sort by Price Desc </button> <button data-bind='click: jumpToFirstPage, enable: gridViewModel.currentPageIndex'> Jump to first page </button> </div> <div> Name:<input type="text" id="text1" value="page1" /> <br /> Age:<input type="text" id="text2" value="1" /> <br /> Height:<input type="text" id="text3" value="2" /> <br /> Weight:<input type="text" id="text4" value="3" /> <br /> <input type="button" value="Post to IIS" onclick="PostData('http://api.asp.net.local/services/restful/api/persons/?NAME=发财發財facai')" /> <br /> <input type="button" value="Post to Self-Host" onclick="PostData('http://localhost:9080/services/restful/api/persons/?NAME=发财發財facai')" /> </div> <script type="text/javascript"> <!-- function PostData(url) { var func = function(scriptCode) { var code = "(" + scriptCode + ");"; return eval(code); }; var jsonText, r; jsonText = '[{Name : "' + document.getElementById("text1").value + "\" ," + "\"Age\" : " + document.getElementById("text2").value + " ," + '"Height" : "' + document.getElementById("text3").value + "\", " + "\"Weight\" : " + document.getElementById("text3").value + ' }]'; //jsonText = '[{"Name":"page1","Age":0,"Height":1,"Weight":2},{"Name":"page2","Age":0,"Height":1,"Weight":2}]';//jsonText, //alert(jsonText); r = func(jsonText); //alert(r[0].Name); $.ajax({ url: url, type: 'POST', data: jsonText,//'[{"Name":"page1","Age":0,"Height":1,"Weight":2},{"Name":"page2","Age":0,"Height":1,"Weight":2}]',//jsonText, //crossDomain: true, dataType: 'json', contentType: "application/json; charset=utf-8", success: function (x) { alert("callback: " + x[0].Name); }, error: function (x) { alert(x); } }); } function GetData(url) { //jsonp cross domain //alert(url); $.getJSON( url , function(data){ //alert(data); $.each(data, function(i ,item){ vm.addItem(item); } ); } ); //jsonp cross domain // $.ajax({ // url : 'http://api.asp.net.local/services/restful/api/persons', // type : 'GET', // dataType : 'jsonp', // success : function (data) { // vm.addItems(data); // } // }); // $.get( // 'http://api.asp.net.local/services/restful/api/persons' // , function (data) { // vm.addItems(data); // } // ); } var PagedGridModel = function(items) { this.items = ko.observableArray(items); this.addItem = function(item) { this.items.push(item); }; this.addItems = function(items) { for (var i in items) { this.items.push(items[i]); } }; this.sortByPriceDesc = function() { this.items.sort(function(a, b) { var r = a.Weight.toFixed(2) < b.Weight.toFixed(2) ? 1 : -1; return r; }); }; this.jumpToFirstPage = function() { this.gridViewModel.currentPageIndex(0); }; this.gridViewModel = new ko.simpleGrid.viewModel( { data: this.items , columns: [ { headerText : "Item Name", rowText : "Name" }, { headerText : "Sales Count", rowText : "Age" }, { headerText : "Price", rowText : function (item) { return "$" + item.Weight.toFixed(2) } } ], pageSize : 9 }); }; var vm = new PagedGridModel([]); ko.applyBindings(vm); //--> </script> </body> </html> */ // Web.Config /* <?xml version="1.0" encoding="utf-8"?> <!-- For more information on how to configure your ASP.NET application, please visit http://go.microsoft.com/fwlink/?LinkId=169433 --> <configuration> <configSections> <section name="glimpse" type="Glimpse.Core.Configuration.Section, Glimpse.Core" /> </configSections> <system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="webHttpBehavior"> <webHttp /> </behavior> </endpointBehaviors> </behaviors> <bindings> <webHttpBinding> <binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true" /> </webHttpBinding> </bindings> <services> <service name="Microshaoft.WCF.Services.PersonsServices"> <endpoint binding="webHttpBinding" bindingConfiguration="webHttpBindingWithJsonP" contract="Microshaoft.WCF.Contracts.IPersonsServices" behaviorConfiguration="webHttpBehavior" /> </service> </services> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> </system.serviceModel> <connectionStrings> <add name="GlimpseAppDB" connectionString="Application Name=GlimpseApp;Persist Security Info=False;Data Source=.\Enterprise2012;Integrated Security=SSPI;" providerName="System.Data.SqlClient" /> </connectionStrings> <system.diagnostics> <sources> <source name="Example Source" switchName="sourceSwitch" switchType="System.Diagnostics.SourceSwitch"> <listeners> <add name="GlimpseListener"/> </listeners> </source> </sources> <switches> <add name="sourceSwitch" value="Warning"/> </switches> <sharedListeners> <add name="GlimpseListener" type="Glimpse.Core.TraceListener, Glimpse.Core"/> </sharedListeners> </system.diagnostics> <system.web> <!-- Glimpse: This can be commented in to add additional data to the Trace tab when using WebForms <trace writeToDiagnosticsTrace="true" enabled="true" pageOutput="false"/> --> <trace enabled="false" pageOutput="false" localOnly="false"/> <httpModules> <add name="Glimpse" type="Glimpse.AspNet.HttpModule, Glimpse.AspNet" /> </httpModules> <httpHandlers> <add path="glimpse.axd" verb="GET" type="Glimpse.AspNet.HttpHandler, Glimpse.AspNet" /> </httpHandlers> <httpRuntime requestPathInvalidCharacters="" requestValidationMode="2.0" /> <pages validateRequest="false" /> </system.web> <system.webServer> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> <add name="Access-Control-Allow-Methods" value="*" /> <add name="Access-Control-Allow-Credentials" value="true" /> <add name="Access-Control-Allow-Headers" value="*, Origin, X-Requested-With, Content-Type, Accept" /> <!-- <add name="Access-Control-Allow-Headers" value="*" /> --> </customHeaders> </httpProtocol> <validation validateIntegratedModeConfiguration="false" /> <handlers> <add name="Glimpse" path="glimpse.axd" verb="GET" type="Glimpse.AspNet.HttpHandler, Glimpse.AspNet" preCondition="integratedMode" /> </handlers> <modules> <add name="Glimpse" type="Glimpse.AspNet.HttpModule, Glimpse.AspNet" preCondition="integratedMode" /> </modules> </system.webServer> <glimpse defaultRuntimePolicy="On" endpointBaseUri="~/Glimpse.axd"> <!-- If you are having issues with Glimpse, please include this. It will help us figure out whats going on. <logging level="Trace" /> --> <!-- Want to use Glimpse on a remote server? Ignore the LocalPolicy by removing this comment. <runtimePolicies> <ignoredTypes> <add type="Glimpse.AspNet.Policy.LocalPolicy, Glimpse.AspNet"/> </ignoredTypes> </runtimePolicies> --> </glimpse> </configuration> */ // Web.Config /* <?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="webHttpBehavior"> <webHttp /> </behavior> </endpointBehaviors> </behaviors> <bindings> <webHttpBinding> <binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true" /> </webHttpBinding> </bindings> <services> <service name="Microshaoft.WCF.Services.PersonsServices"> <!-- address="http://api.asp.net.local:1080/services/restful/wcf/persons" --> <endpoint address="http://api.asp.net.local:1080/services/restful/wcf/persons" binding="webHttpBinding" bindingConfiguration="webHttpBindingWithJsonP" contract="Microshaoft.WCF.Contracts.IPersonsServices" behaviorConfiguration="webHttpBehavior" /> </service> </services> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> </system.serviceModel> </configuration> */ |