Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / xsp / System / Web / Extensions / Script / Services / RestHandler.cs / 1 / RestHandler.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Web.Script.Services { using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Net; using System.Reflection; using System.Security; using System.Text; using System.Web; using System.Web.Resources; using System.Web.Script.Serialization; using System.Web.SessionState; internal class RestHandler : IHttpHandler { private WebServiceMethodData _webServiceMethodData; internal static IHttpHandler CreateHandler(HttpContext context) { // Expectation is that we got a PathInfo of form /MethodName if (context.Request.PathInfo.Length < 2 || context.Request.PathInfo[0] != '/') { throw new InvalidOperationException(AtlasWeb.WebService_InvalidWebServiceCall); } // Get the data about the web service being invoked WebServiceData webServiceData = WebServiceData.GetWebServiceData(context, context.Request.FilePath); string methodName = context.Request.PathInfo.Substring(1); return CreateHandler(webServiceData, methodName); } private static IHttpHandler CreateHandler(WebServiceData webServiceData, string methodName) { // Get the data about the method being called WebServiceMethodData methodData = webServiceData.GetMethodData(methodName); // Create the proper handler, depending on whether we need session state RestHandler handler; if (methodData.RequiresSession) handler = new RestHandlerWithSession(); else handler = new RestHandler(); // Save the method data in the handler handler._webServiceMethodData = methodData; return handler; } // This is very similar to WebService caching, the differences are // 1) Here we explicitely SetValidUntilExpires(true) because in an XmlHttp there is // "pragma:no-cache" in header which would result in cache miss on the server. // 2) Here we don't vary on header "Content-type" or "SOAPAction" because the former // is specific to soap 1.2, which puts action in the content-type param; and the // later is used by soap calls. private static void InitializeCachePolicy(WebServiceMethodData methodData, HttpContext context) { int cacheDuration = methodData.CacheDuration; if (cacheDuration > 0) { context.Response.Cache.SetCacheability(HttpCacheability.Server); context.Response.Cache.SetExpires(DateTime.Now.AddSeconds(cacheDuration)); context.Response.Cache.SetSlidingExpiration(false); context.Response.Cache.SetValidUntilExpires(true); // DevDiv 23596: Don't set VaryBy* if the method takes no parameters if (methodData.ParameterDatas.Count > 0) { context.Response.Cache.VaryByParams["*"] = true; } else { context.Response.Cache.VaryByParams.IgnoreParams = true; } } else { context.Response.Cache.SetNoServerCaching(); context.Response.Cache.SetMaxAge(TimeSpan.Zero); } } private static IDictionaryGetRawParamsFromGetRequest(HttpContext context, JavaScriptSerializer serializer, WebServiceMethodData methodData) { // Get all the parameters from the query string NameValueCollection queryString = context.Request.QueryString; Dictionary rawParams = new Dictionary (); foreach (WebServiceParameterData param in methodData.ParameterDatas) { string name = param.ParameterInfo.Name; string val = queryString[name]; if (val != null) { rawParams.Add(name, serializer.DeserializeObject(val)); } } return rawParams; } private static IDictionary GetRawParamsFromPostRequest(HttpContext context, JavaScriptSerializer serializer) { // Read the entire body as a string TextReader reader = new StreamReader(context.Request.InputStream); string bodyString = reader.ReadToEnd(); // If there is no body, treat it as an empty object if (String.IsNullOrEmpty(bodyString)) { return new Dictionary (); } // Deserialize the javascript request body return serializer.Deserialize >(bodyString); } private static IDictionary GetRawParams(WebServiceMethodData methodData, HttpContext context) { if (methodData.UseGet) { if (context.Request.HttpMethod == "GET") { return GetRawParamsFromGetRequest(context, methodData.Owner.Serializer, methodData); } else { throw new InvalidOperationException( String.Format(CultureInfo.CurrentCulture, AtlasWeb.WebService_InvalidVerbRequest, methodData.MethodName, "POST")); } } else if (context.Request.HttpMethod == "POST") { return GetRawParamsFromPostRequest(context, methodData.Owner.Serializer); } else { throw new InvalidOperationException( String.Format(CultureInfo.CurrentCulture, AtlasWeb.WebService_InvalidVerbRequest, methodData.MethodName, "GET")); } } private static void InvokeMethod(HttpContext context, WebServiceMethodData methodData, IDictionary rawParams) { // Initialize HttpCachePolicy InitializeCachePolicy(methodData, context); // Create an new instance of the class object target = null; if (!methodData.IsStatic) target = Activator.CreateInstance(methodData.Owner.TypeData.Type); // Make the actual method call on it object retVal = methodData.CallMethodFromRawParams(target, rawParams); string contentType; string responseString = null; if (methodData.UseXmlResponse) { responseString = retVal as string; // If it's a string, output it as is unless XmlSerializeString is set if (responseString == null || methodData.XmlSerializeString) { // Use the Xml Serializer try { responseString = ServicesUtilities.XmlSerializeObjectToString(retVal); } catch (Exception e) { // Throw a better error if Xml serialization fails throw new InvalidOperationException( String.Format(CultureInfo.CurrentCulture, AtlasWeb.WebService_InvalidXmlReturnType, methodData.MethodName, retVal.GetType().FullName, e.Message)); } } contentType = "text/xml"; } else { // Convert the result to a JSON string // DevDiv 88409:Change JSON wire format to prevent CSRF attack // We wrap the returned value inside an object , and assign the returned value // to member "d" of the object. We do so as JSOM for object will never be parsed // as valid Javascript , unlike arrays. responseString =@"{""d"":" + methodData.Owner.Serializer.Serialize(retVal) + "}"; contentType = "application/json"; } // Set the response content-type context.Response.ContentType = contentType; // Write the string to the response if (responseString != null) context.Response.Write(responseString); } [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification="All exceptions need to be reported to the client")] [SuppressMessage("Microsoft.Security", "CA2107:ReviewDenyAndPermitOnlyUsage", Justification = "Fix for DevDiv 39162 GAC'd non-APTCA types can instantiate in networking stack in Medium trust")] internal static void ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData) { try { NamedPermissionSet s_permissionSet = HttpRuntime.NamedPermissionSet; if (s_permissionSet != null) { s_permissionSet.PermitOnly(); } // Deserialize the javascript request body IDictionary rawParams = GetRawParams(methodData, context); InvokeMethod(context, methodData, rawParams); } catch (Exception ex) { WriteExceptionJsonString(context, ex); } } internal class WebServiceError { public string Message; public string StackTrace; public string ExceptionType; public WebServiceError(string msg, string stack, string type) { Message = msg; StackTrace = stack; ExceptionType = type; } } internal static void WriteExceptionJsonString(HttpContext context, Exception ex) { WriteExceptionJsonString(context, ex, (int)HttpStatusCode.InternalServerError); } internal static void WriteExceptionJsonString(HttpContext context, Exception ex, int statusCode) { // Record the charset before we call ClearHeaders(). (DevDiv Bugs 158401) string charset = context.Response.Charset; context.Response.ClearHeaders(); context.Response.ClearContent(); context.Response.Clear(); context.Response.StatusCode = statusCode; context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription(statusCode); context.Response.ContentType = "application/json"; context.Response.AddHeader("jsonerror", "true"); // Maintain the Charset from before. (DevDiv Bugs 158401) context.Response.Charset = charset; //Devdiv Bug: 118619:When accessed remotely, an Ajax web service that throws an error doesn't return the error string in the proper format on IIS7 //For IIS 7.0 integrated mode we need to set TrySkipIisCustomErrors to override IIS custom error handling. This has no functional/perf impact on //IIS 7.0 classic mode or earlier versions. context.Response.TrySkipIisCustomErrors = true; using (StreamWriter writer = new StreamWriter(context.Response.OutputStream, new UTF8Encoding(false))) { if (ex is TargetInvocationException) { ex = ex.InnerException; } // Don't show any error stack or sensitive info when custom error is enabled. if (context.IsCustomErrorEnabled) { writer.Write(JavaScriptSerializer.SerializeInternal(new WebServiceError(AtlasWeb.WebService_Error, String.Empty, String.Empty))); } else { writer.Write(JavaScriptSerializer.SerializeInternal(new WebServiceError(ex.Message, ex.StackTrace, ex.GetType().FullName))); } writer.Flush(); } } public void ProcessRequest(HttpContext context) { ExecuteWebServiceCall(context, _webServiceMethodData); } public bool IsReusable { get { return false; } } } // Same handler, but implementing IRequiresSessionState to allow session state use internal class RestHandlerWithSession: RestHandler, IRequiresSessionState { } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Web.Script.Services { using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Net; using System.Reflection; using System.Security; using System.Text; using System.Web; using System.Web.Resources; using System.Web.Script.Serialization; using System.Web.SessionState; internal class RestHandler : IHttpHandler { private WebServiceMethodData _webServiceMethodData; internal static IHttpHandler CreateHandler(HttpContext context) { // Expectation is that we got a PathInfo of form /MethodName if (context.Request.PathInfo.Length < 2 || context.Request.PathInfo[0] != '/') { throw new InvalidOperationException(AtlasWeb.WebService_InvalidWebServiceCall); } // Get the data about the web service being invoked WebServiceData webServiceData = WebServiceData.GetWebServiceData(context, context.Request.FilePath); string methodName = context.Request.PathInfo.Substring(1); return CreateHandler(webServiceData, methodName); } private static IHttpHandler CreateHandler(WebServiceData webServiceData, string methodName) { // Get the data about the method being called WebServiceMethodData methodData = webServiceData.GetMethodData(methodName); // Create the proper handler, depending on whether we need session state RestHandler handler; if (methodData.RequiresSession) handler = new RestHandlerWithSession(); else handler = new RestHandler(); // Save the method data in the handler handler._webServiceMethodData = methodData; return handler; } // This is very similar to WebService caching, the differences are // 1) Here we explicitely SetValidUntilExpires(true) because in an XmlHttp there is // "pragma:no-cache" in header which would result in cache miss on the server. // 2) Here we don't vary on header "Content-type" or "SOAPAction" because the former // is specific to soap 1.2, which puts action in the content-type param; and the // later is used by soap calls. private static void InitializeCachePolicy(WebServiceMethodData methodData, HttpContext context) { int cacheDuration = methodData.CacheDuration; if (cacheDuration > 0) { context.Response.Cache.SetCacheability(HttpCacheability.Server); context.Response.Cache.SetExpires(DateTime.Now.AddSeconds(cacheDuration)); context.Response.Cache.SetSlidingExpiration(false); context.Response.Cache.SetValidUntilExpires(true); // DevDiv 23596: Don't set VaryBy* if the method takes no parameters if (methodData.ParameterDatas.Count > 0) { context.Response.Cache.VaryByParams["*"] = true; } else { context.Response.Cache.VaryByParams.IgnoreParams = true; } } else { context.Response.Cache.SetNoServerCaching(); context.Response.Cache.SetMaxAge(TimeSpan.Zero); } } private static IDictionaryGetRawParamsFromGetRequest(HttpContext context, JavaScriptSerializer serializer, WebServiceMethodData methodData) { // Get all the parameters from the query string NameValueCollection queryString = context.Request.QueryString; Dictionary rawParams = new Dictionary (); foreach (WebServiceParameterData param in methodData.ParameterDatas) { string name = param.ParameterInfo.Name; string val = queryString[name]; if (val != null) { rawParams.Add(name, serializer.DeserializeObject(val)); } } return rawParams; } private static IDictionary GetRawParamsFromPostRequest(HttpContext context, JavaScriptSerializer serializer) { // Read the entire body as a string TextReader reader = new StreamReader(context.Request.InputStream); string bodyString = reader.ReadToEnd(); // If there is no body, treat it as an empty object if (String.IsNullOrEmpty(bodyString)) { return new Dictionary (); } // Deserialize the javascript request body return serializer.Deserialize >(bodyString); } private static IDictionary GetRawParams(WebServiceMethodData methodData, HttpContext context) { if (methodData.UseGet) { if (context.Request.HttpMethod == "GET") { return GetRawParamsFromGetRequest(context, methodData.Owner.Serializer, methodData); } else { throw new InvalidOperationException( String.Format(CultureInfo.CurrentCulture, AtlasWeb.WebService_InvalidVerbRequest, methodData.MethodName, "POST")); } } else if (context.Request.HttpMethod == "POST") { return GetRawParamsFromPostRequest(context, methodData.Owner.Serializer); } else { throw new InvalidOperationException( String.Format(CultureInfo.CurrentCulture, AtlasWeb.WebService_InvalidVerbRequest, methodData.MethodName, "GET")); } } private static void InvokeMethod(HttpContext context, WebServiceMethodData methodData, IDictionary rawParams) { // Initialize HttpCachePolicy InitializeCachePolicy(methodData, context); // Create an new instance of the class object target = null; if (!methodData.IsStatic) target = Activator.CreateInstance(methodData.Owner.TypeData.Type); // Make the actual method call on it object retVal = methodData.CallMethodFromRawParams(target, rawParams); string contentType; string responseString = null; if (methodData.UseXmlResponse) { responseString = retVal as string; // If it's a string, output it as is unless XmlSerializeString is set if (responseString == null || methodData.XmlSerializeString) { // Use the Xml Serializer try { responseString = ServicesUtilities.XmlSerializeObjectToString(retVal); } catch (Exception e) { // Throw a better error if Xml serialization fails throw new InvalidOperationException( String.Format(CultureInfo.CurrentCulture, AtlasWeb.WebService_InvalidXmlReturnType, methodData.MethodName, retVal.GetType().FullName, e.Message)); } } contentType = "text/xml"; } else { // Convert the result to a JSON string // DevDiv 88409:Change JSON wire format to prevent CSRF attack // We wrap the returned value inside an object , and assign the returned value // to member "d" of the object. We do so as JSOM for object will never be parsed // as valid Javascript , unlike arrays. responseString =@"{""d"":" + methodData.Owner.Serializer.Serialize(retVal) + "}"; contentType = "application/json"; } // Set the response content-type context.Response.ContentType = contentType; // Write the string to the response if (responseString != null) context.Response.Write(responseString); } [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification="All exceptions need to be reported to the client")] [SuppressMessage("Microsoft.Security", "CA2107:ReviewDenyAndPermitOnlyUsage", Justification = "Fix for DevDiv 39162 GAC'd non-APTCA types can instantiate in networking stack in Medium trust")] internal static void ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData) { try { NamedPermissionSet s_permissionSet = HttpRuntime.NamedPermissionSet; if (s_permissionSet != null) { s_permissionSet.PermitOnly(); } // Deserialize the javascript request body IDictionary rawParams = GetRawParams(methodData, context); InvokeMethod(context, methodData, rawParams); } catch (Exception ex) { WriteExceptionJsonString(context, ex); } } internal class WebServiceError { public string Message; public string StackTrace; public string ExceptionType; public WebServiceError(string msg, string stack, string type) { Message = msg; StackTrace = stack; ExceptionType = type; } } internal static void WriteExceptionJsonString(HttpContext context, Exception ex) { WriteExceptionJsonString(context, ex, (int)HttpStatusCode.InternalServerError); } internal static void WriteExceptionJsonString(HttpContext context, Exception ex, int statusCode) { // Record the charset before we call ClearHeaders(). (DevDiv Bugs 158401) string charset = context.Response.Charset; context.Response.ClearHeaders(); context.Response.ClearContent(); context.Response.Clear(); context.Response.StatusCode = statusCode; context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription(statusCode); context.Response.ContentType = "application/json"; context.Response.AddHeader("jsonerror", "true"); // Maintain the Charset from before. (DevDiv Bugs 158401) context.Response.Charset = charset; //Devdiv Bug: 118619:When accessed remotely, an Ajax web service that throws an error doesn't return the error string in the proper format on IIS7 //For IIS 7.0 integrated mode we need to set TrySkipIisCustomErrors to override IIS custom error handling. This has no functional/perf impact on //IIS 7.0 classic mode or earlier versions. context.Response.TrySkipIisCustomErrors = true; using (StreamWriter writer = new StreamWriter(context.Response.OutputStream, new UTF8Encoding(false))) { if (ex is TargetInvocationException) { ex = ex.InnerException; } // Don't show any error stack or sensitive info when custom error is enabled. if (context.IsCustomErrorEnabled) { writer.Write(JavaScriptSerializer.SerializeInternal(new WebServiceError(AtlasWeb.WebService_Error, String.Empty, String.Empty))); } else { writer.Write(JavaScriptSerializer.SerializeInternal(new WebServiceError(ex.Message, ex.StackTrace, ex.GetType().FullName))); } writer.Flush(); } } public void ProcessRequest(HttpContext context) { ExecuteWebServiceCall(context, _webServiceMethodData); } public bool IsReusable { get { return false; } } } // Same handler, but implementing IRequiresSessionState to allow session state use internal class RestHandlerWithSession: RestHandler, IRequiresSessionState { } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- HighContrastHelper.cs
- returneventsaver.cs
- CultureInfo.cs
- Rotation3DAnimationBase.cs
- SerialStream.cs
- DoubleLink.cs
- KnownTypes.cs
- StringFreezingAttribute.cs
- PopupControlService.cs
- UniqueIdentifierService.cs
- DesignColumn.cs
- XPathParser.cs
- DataControlField.cs
- XmlHierarchyData.cs
- SafeFileMappingHandle.cs
- UnaryOperationBinder.cs
- ThemeDictionaryExtension.cs
- LocationReferenceValue.cs
- sqlinternaltransaction.cs
- WindowsTooltip.cs
- CodeSnippetExpression.cs
- ScrollBar.cs
- GeometryModel3D.cs
- CacheDependency.cs
- BitConverter.cs
- SiteMapDataSource.cs
- ProtocolImporter.cs
- NonClientArea.cs
- GridPatternIdentifiers.cs
- WeakEventTable.cs
- TranslateTransform3D.cs
- InnerItemCollectionView.cs
- PrivateFontCollection.cs
- ExceptionAggregator.cs
- InternalDispatchObject.cs
- StateMachineAction.cs
- CSharpCodeProvider.cs
- IERequestCache.cs
- WmfPlaceableFileHeader.cs
- HeaderCollection.cs
- HttpCookie.cs
- UICuesEvent.cs
- VideoDrawing.cs
- OptionUsage.cs
- Compiler.cs
- ListViewInsertedEventArgs.cs
- ClientProxyGenerator.cs
- DBConnection.cs
- KeyedHashAlgorithm.cs
- Win32KeyboardDevice.cs
- ExpandedProjectionNode.cs
- DictionaryKeyPropertyAttribute.cs
- DesignTimeTemplateParser.cs
- GridViewPageEventArgs.cs
- ProtocolProfile.cs
- Panel.cs
- QueryStatement.cs
- ThrowHelper.cs
- ClientRolePrincipal.cs
- SystemIPv6InterfaceProperties.cs
- ParameterElementCollection.cs
- UserMapPath.cs
- BodyWriter.cs
- Catch.cs
- XPathBinder.cs
- ValidatorAttribute.cs
- DetailsViewRow.cs
- QuaternionConverter.cs
- BitmapEncoder.cs
- ClientConvert.cs
- XmlChildNodes.cs
- ContainerParaClient.cs
- SoapElementAttribute.cs
- ArrayListCollectionBase.cs
- UTF8Encoding.cs
- Membership.cs
- HtmlTextArea.cs
- MSAAWinEventWrap.cs
- DataGridViewColumnDesignTimeVisibleAttribute.cs
- StrongNamePublicKeyBlob.cs
- EntityClassGenerator.cs
- UTF8Encoding.cs
- Lazy.cs
- RelationHandler.cs
- ObjectHandle.cs
- PointKeyFrameCollection.cs
- VariableQuery.cs
- HandledEventArgs.cs
- SafeCryptContextHandle.cs
- UnsafeNativeMethodsPenimc.cs
- DbParameterCollectionHelper.cs
- DocumentPageViewAutomationPeer.cs
- NavigationEventArgs.cs
- ToolStripContentPanelRenderEventArgs.cs
- ManagedWndProcTracker.cs
- XmlDesignerDataSourceView.cs
- SocketInformation.cs
- BindingCompleteEventArgs.cs
- DebugView.cs
- TdsValueSetter.cs