Some pitfall and pitfall
1) We often use feature filters. They are generally used to capture exceptions and control permissions. This is easy to use, but it does hide a pitfall, the feature filter is created once when it is accessed for the first time. It is only created once, and then cached by aspnet. So if we want to define a feature class, we must note that it cannot contain local variables with variable states, because there will be thread security issues. 2) about the nuget assembly version, there are many places in our program that use nuget, but sometimes we will see different nuget package versions referenced by different assembly, however, after the program is compiled, only one version of dll will be available in the web directory. In this way, if a package with a strong name is used, a version exception will be thrown, therefore, we recommend that you keep all the Assembly versions the same. Of course, there is also an emergency solution, that is, the function of this node under webconfig is Assembly redirection. When the Assembly version check is performed, the reference to the old version will be redirected to the new version 3) thread-safe Dictionary of a set <,>, List <>: thread-unsafe: A version field is maintained when you add or delete a set, the version number will be introduced when the iterator is generated after the first iteration. Then, the iterator will judge whether the version of the iterator is the same as the version number during the iteration, if they are different, an exception is thrown. Therefore, if concurrent operations occur, when one thread is querying the dic, another thread modifies the dic And throws an exception. The ConcurrentDictionary thread uses volatile to set the thread security and does not maintain the version field. 4) currently, we need to use Https for https, so the page will also be compatible with the request content. For http requests, we need to return static content with the http suffix, https returns static content with the https suffix, so we will think of using the Request Method to Determine, get the user's request method in the program, the above method is problematic, and the problem is only found in the production environment: Because the certificate in the production environment is configured on the nginx server, therefore, https will only arrive at nginx. When nginx is forwarded to our web server, it is still an http request, therefore, this method is always http in the production environment. Therefore, the recommended solution is to configure the static address without adding the protocol header. src can be directly written as "// res.rongzi.com ..... "In this way, the browser will identify which protocol is used according to the specific request. 5) Currently, the code in our project is used to using (HttpClient client = new HttpClient) {} but there is a problem with this writing: 1. HttpClient itself maintains a connection pool, therefore, the HttpClient only needs to be instantiated to meet all requirements. 2. If the above call method is complete, the client's DIspose method will be called to release the pool, it takes about four minutes to completely release the pool. Therefore, this will lead to a problem, that is, if the request reaches a certain level within four minutes, the socket will be exhausted, to throw an exception (the main site has encountered such a problem) specific article link: http://www.infoq.com/cn/news/2016/09/HttpClient In this case, I encapsulate an HttpHelper class to process requests:
Using Newtonsoft. json; using System. collections. generic; using System. IO; using System. linq; using System. net. http; using System. runtime. serialization. json; using System. text; using System. text. regularExpressions; using System. threading. tasks; namespace Platform. facilitys {public static class HttpHelper {static readonly HttpClient _ client; static HttpHelper () {_ client = new HttpClient ();} pu Blic static TOut PostSync <TIn, TOut> (ApiHost host, TIn postData) where TIn: class where TOut: class {var uri = new Uri (host. domain); var url = new Uri (uri, host. apiName); var response = _ client. postAsync (url, new StringContent (JsonConvert. serializeObject (postData), Encoding. UTF8, host. dataMimeType )). result; response. ensureSuccessStatusCode (); return response. content. desObj <TOut> ();} public stati C Task <TOut> PostAsync <TIn, TOut> (ApiHost host, TIn postData) where TIn: class where TOut: class {var uri = new Uri (host. domain); var url = new Uri (uri, host. apiName); return _ client. postAsync (url, new StringContent (JsonConvert. serializeObject (postData), Encoding. UTF8, host. dataMimeType )). getResult <TOut> ();} public static Task <TOut> GetAsync <TOut> (ApiHost host) where TOut: class {var uri = n Ew Uri (host. domain); var url = new Uri (uri, host. apiName); return _ client. getAsync (url ). getResult <TOut> ();} static Task <TOut> GetResult <TOut> (this Task <HttpResponseMessage> tsk) where TOut: class {return tsk. continueWith (res => {return res. result. ensureSuccessStatusCode (). content. desObj <TOut> () ;}, TaskContinuationOptions. onlyOnRanToCompletion);} static TOut DesObj <TOut> (this HttpContent Content) where TOut: class {var strJson = content. ReadAsStringAsync (). Result; if (! String. isNullOrWhiteSpace (strJson) {if (strJson. indexOf ("k _ BackingField")> 0) {DataContractJsonSerializer ser = new DataContractJsonSerializer (typeof (TOut); using (var mStream = new MemoryStream (Encoding. default. getBytes (strJson) {return ser. readObject (mStream) as TOut;} else {return JsonConvert. deserializeObject <TOut> (strJson) ;}} return default (TOut );}} /// <summary> /// WebApi configuration /// </summary> public class ApiHost {# region public ApiHost () {DataMimeType = "application/json ";} public ApiHost (string domain, string apiName, string inputQueryString, string dataMimeType) {Domain = domain; ApiName = apiName; InputQueryString = inputQueryString; DataMimeType = dataMimeType ;} # endregion # region // <summary> // primary domain name (for example http://api.rongzi.com Or http://127.0.0.1 ) /// </Summary> public string Domain {get; set ;}/// <summary> // Api name (api/v1/studentinfotest) /// </summary> public string ApiName {get; set ;} /// <summary> /// input parameter name /// </summary> public string InputQueryString {get; set ;} /// <summary> /// return data type /// </summary> public string DataMimeType {get; set ;} /// <summary> /// rewrite ToString () /// </summary> /// <returns> </returns> public override string ToString () {return string. format ("{0} | {1} | {2} | {3}", this. apiName, this. domain, this. dataMimeType, this. inputQueryString) ;}# endregion }}
6) concerning the thread storage, during the development process, sometimes some objects and other things need to be transmitted from the front to the back in a web lifecycle. In this case, a method CallContext may be used. setData is used to set the data. This method stores the content in the thread, so you can obtain this content in the same thread. However, if this Action is asynchronous, async, this will lead to multiple threads processing this request in turn. In this case, the previously set value is often not obtained. At this time, CallContext can be used. logicSetData to set the value. The content set in this way will be copied to the new thread.