private static void InvokeMethod(HttpContext context, WebServiceMethodData methodData, IDictionary <string, object> 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); } }
private static IDictionary <string, object> 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")); } }
// 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 IDictionary<string, object> GetRawParamsFromGetRequest(HttpContext context, JavaScriptSerializer serializer, WebServiceMethodData methodData) { // Get all the parameters from the query string NameValueCollection queryString = context.Request.QueryString; Dictionary<string, object> rawParams = new Dictionary<string, object>(); 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; }
internal WebServiceMethodData GetMethodData(string methodName) { EnsureMethods(); // Fail if the web method doesn't exist WebServiceMethodData methodData = null; if (!_methods.TryGetValue(methodName, out methodData)) { throw new ArgumentException( String.Format(CultureInfo.CurrentCulture, AtlasWeb.WebService_UnknownWebMethod, methodName), "methodName"); } EnsureClientTypesProcessed(); return(methodData); }
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 <string, object> rawParams = GetRawParams(methodData, context); InvokeMethod(context, methodData, rawParams); } catch (Exception ex) { WriteExceptionJsonString(context, ex); } }
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); }
private void BuildArgsDictionary(WebServiceMethodData methodData, StringBuilder args, StringBuilder argsDict, StringBuilder docComments) { argsDict.Append('{'); foreach (WebServiceParameterData paramData in methodData.ParameterDatas) { string name = paramData.ParameterName; if (docComments != null) { // looks like: /// <param name="foo" type="ClientType">Namespace.ServerType</param> // client type may not match server type for built in js types like date, number, etc. // client type may be omitted for type Object. docComments.Append("/// <param name=\"").Append(name).Append("\""); Type serverType = ServicesUtilities.UnwrapNullableType(paramData.ParameterType); string clientType = GetClientTypeNamespace(ServicesUtilities.GetClientTypeFromServerType(methodData.Owner, serverType)); if (!String.IsNullOrEmpty(clientType)) { docComments.Append(" type=\"").Append(clientType).Append("\""); } docComments.Append(">").Append(serverType.FullName).Append("</param>\r\n"); } if (args.Length > 0) { args.Append(','); argsDict.Append(','); } args.Append(name); argsDict.Append(name).Append(':').Append(name); } if (docComments != null) { // append the built-in comments that all methods have (success, failed, usercontext parameters) docComments.Append(DebugXmlComments); } argsDict.Append("}"); if (args.Length > 0) { args.Append(','); } args.Append("succeededCallback, failedCallback, userContext"); }
private void GenerateWebMethodProxy(WebServiceMethodData methodData) { string methodName = methodData.MethodName; string typeName = GetProxyTypeName(methodData.Owner); string useGet = methodData.UseGet ? "true" : "false"; _builder.Append(methodName).Append(':'); // e.g. MyMethod : function(param1, param2, ..., OnSuccess, OnFailure) StringBuilder args = new StringBuilder(); StringBuilder argsDict = new StringBuilder(); StringBuilder docComments = null; string docCommentsString = null; if (_debugMode) { docComments = new StringBuilder(); } BuildArgsDictionary(methodData, args, argsDict, docComments); if (_debugMode) { // Remember the doc comments for the static instance case docCommentsString = docComments.ToString(); _docCommentCache[methodName] = docCommentsString; } // Method calls look like this.invoke(FooNS.Sub.Method.get_path(), 'MethodName', true[useGet], {'arg1':'val1', 'arg2':'val2' }, onComplete, onError, userContext, 'FooNS.Sub.Method') _builder.Append("function(").Append(args.ToString()).Append(") {\r\n"); if (_debugMode) { // docCommentsString always end in \r\n _builder.Append(docCommentsString); } _builder.Append("return this._invoke(this._get_path(), "); _builder.Append("'").Append(methodName).Append("',"); _builder.Append(useGet).Append(','); _builder.Append(argsDict.ToString()).Append(",succeededCallback,failedCallback,userContext); }"); }
private void AddMethod(Dictionary <string, WebServiceMethodData> methods, MethodInfo method) { object[] wmAttribs = method.GetCustomAttributes(typeof(WebMethodAttribute), true); // Skip it if it doesn't have the WebMethod attribute if (wmAttribs.Length == 0) { return; } ScriptMethodAttribute sm = null; object[] responseAttribs = method.GetCustomAttributes(typeof(ScriptMethodAttribute), true); if (responseAttribs.Length > 0) { sm = (ScriptMethodAttribute)responseAttribs[0]; } // Create an object to keep track of this method's data WebServiceMethodData wmd = new WebServiceMethodData(this, method, (WebMethodAttribute)wmAttribs[0], sm); methods[wmd.MethodName] = wmd; }
private static IDictionary <string, object> GetRawParamsFromGetRequest(HttpContext context, JavaScriptSerializer serializer, WebServiceMethodData methodData) { // Get all the parameters from the query string NameValueCollection queryString = context.Request.QueryString; Dictionary <string, object> rawParams = new Dictionary <string, object>(); 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 void AddMethod(Dictionary<string, WebServiceMethodData> methods, MethodInfo method) { object[] wmAttribs = method.GetCustomAttributes(typeof(WebMethodAttribute), true); // Skip it if it doesn't have the WebMethod attribute if (wmAttribs.Length == 0) return; ScriptMethodAttribute sm = null; object[] responseAttribs = method.GetCustomAttributes(typeof(ScriptMethodAttribute), true); if (responseAttribs.Length > 0) { sm = (ScriptMethodAttribute)responseAttribs[0]; } // Create an object to keep track of this method's data WebServiceMethodData wmd = new WebServiceMethodData(this, method, (WebMethodAttribute)wmAttribs[0], sm); methods[wmd.MethodName] = wmd; }
private static IDictionary<string, object> 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<string, object> 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); }
static WebServiceData GetWebServiceData(ContractDescription contract) { WebServiceData serviceData = new WebServiceData(); //build method dictionary Dictionary<string, WebServiceMethodData> methodDataDictionary = new Dictionary<string, WebServiceMethodData>(); // set service type serviceData.Initialize(new WebServiceTypeData(XmlConvert.DecodeName(contract.Name), XmlConvert.DecodeName(contract.Namespace), contract.ContractType), methodDataDictionary); foreach (OperationDescription operation in contract.Operations) { Dictionary<string, WebServiceParameterData> parameterDataDictionary = new Dictionary<string, WebServiceParameterData>(); bool useHttpGet = operation.Behaviors.Find<WebGetAttribute>() != null; WebServiceMethodData methodData = new WebServiceMethodData(serviceData, XmlConvert.DecodeName(operation.Name), parameterDataDictionary, useHttpGet); // build parameter dictionary MessageDescription requestMessage = operation.Messages[0]; if (requestMessage != null) { int numMessageParts = requestMessage.Body.Parts.Count; for (int p = 0; p < numMessageParts; p++) { MessagePartDescription messagePart = requestMessage.Body.Parts[p]; // DevDiv 129964:JS proxy generation fails for a WCF service that uses an untyped message // Message or its derived class are special, used for untyped operation contracts. // As per the WCF team proxy generated for them should treat Message equivalent to Object type. Type paramType = ReplaceMessageWithObject(messagePart.Type); WebServiceParameterData parameterData = new WebServiceParameterData(XmlConvert.DecodeName(messagePart.Name), paramType, p); parameterDataDictionary[parameterData.ParameterName] = parameterData; serviceData.ProcessClientType(paramType, false, true); } } if (operation.Messages.Count > 1) { // its a two way operation, get type information from return message MessageDescription responseMessage = operation.Messages[1]; if (responseMessage != null) { if (responseMessage.Body.ReturnValue != null && responseMessage.Body.ReturnValue.Type != null) { // operation has a return type, add type to list of type proxy to generate serviceData.ProcessClientType(ReplaceMessageWithObject(responseMessage.Body.ReturnValue.Type), false, true); } } } //add known types at operation level for (int t = 0; t < operation.KnownTypes.Count; t++) { serviceData.ProcessClientType(operation.KnownTypes[t], false, true); } methodDataDictionary[methodData.MethodName] = methodData; } serviceData.ClearProcessedTypes(); return serviceData; }
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<string, object> rawParams = GetRawParams(methodData, context); InvokeMethod(context, methodData, rawParams); } catch (Exception ex) { WriteExceptionJsonString(context, ex); } }