/// <summary>
        /// Erstellen eines einfachen HREF Links für window.location.href
        /// </summary>
        public string BuildHrefLink(ProxyMethodInfos methodInfo, ProxyBuilder proxyBuilder)
        {
            //z.B.: window.location.href = window.siteRoot + 'Auftragsabrechnung/ExportData' + '?allEntries=' + encodeURIComponent(allEntries) + '&' + jQuery.param($scope.FilterData);
            //Wir bauen hier aber nur den Link Teil zusammen: 'Auftragsabrechnung/ExportData' + '?allEntries=' + encodeURIComponent(allEntries) + '&' + jQuery.param($scope.FilterData);

            StringBuilder builder = new StringBuilder();
            builder.Append(string.Format("'{0}/{1}'", ProxyBuilderHelper.GetClearControllerName(methodInfo.Controller), methodInfo.MethodInfo.Name));
            builder.Append(ProxyBuilderHelper.BuildUrlParameterId(methodInfo.ProxyMethodParameterInfos));
            //Da wir die Komplexen Parameter nicht als Post mit übergeben können bei einem Link, müssen wird diese entsprechend in Url Parametern abbilden.
            builder.Append(ProxyBuilderHelper.BuildComplexUrlParameter(methodInfo.ProxyMethodParameterInfos));
            return builder.ToString();
        }
        public void BuildGet_NoComplexType_WithId()
        {
            //Arrange
            var methodInfos = new ProxyMethodInfos();
            //Die MethodenInfos laden - können wir nicht Mocken!
            methodInfos.MethodInfo = TestClassType.GetMethod("OneParam");
            methodInfos.ProxyMethodParameterInfos.Add(new ProxyMethodParameterInfo() { IsComplexeType = false, ParameterName = "id"});

            //Mocken der passenden Infos
            MockBuildHelper.Setup(p => p.GetClearControllerName(It.IsAny<Type>())).Returns("Home");
            MockBuildHelper.Setup(p => p.BuildUrlParameterId(It.IsAny<List<ProxyMethodParameterInfo>>())).Returns(" + '/' + id ");
            MockBuildHelper.Setup(p => p.BuildUrlParameter(It.IsAny<List<ProxyMethodParameterInfo>>())).Returns(" + '?name='+encodeURIComponent(name)");

            //Act
            var getParams = ProxyBuilderHttpCall.BuildHttpCall(methodInfos, ProxyBuilder.AngularJavaScript);

            //Assert
            Assert.AreEqual(getParams, "get('Home/OneParam' + '/' + id  + '?name='+encodeURIComponent(name))");
        }
        /// <summary>
        /// Laden der Methodeninformationen für die übergebene Klasse (Controller)
        /// </summary>
        public List<ProxyMethodInfos> LoadMethodInfos(Type controller, Type proxyTypeAttribute)
        {
            List<ProxyMethodInfos> proxyMethodInfos = new List<ProxyMethodInfos>();

            //Alle Methoden des Controllers durchgehen und nur die Methoden ermitteln in denen auch das übergebene ProxyAttribut enthalten ist.
            foreach (MethodInfo methodInfo in controller.GetMethods().Where(p => p.GetCustomAttributes(true).Any(attr => attr.GetType() == proxyTypeAttribute)))
            {
                if (proxyMethodInfos.Any(p => p.MethodInfo.Name == methodInfo.Name))
                {
                    throw new Exception(string.Format("ERROR, JavaScript doesn't supports function/method overload, please rename one of those functions/methods '{0}'", methodInfo.Name));
                }

                ProxyMethodInfos proxyMethodInfo = new ProxyMethodInfos();
                //Laden der Paramterinformationen zu unserer Methode.
                proxyMethodInfo.ProxyMethodParameterInfos = Factory.CreateMethodParameterManager().LoadParameterInfos(methodInfo);
                proxyMethodInfo.MethodInfo = methodInfo;
                proxyMethodInfo.Controller = controller;
                proxyMethodInfo.ReturnType = GetProxyReturnType(methodInfo);
                proxyMethodInfo.CreateWindowLocationHrefLink = GetCreateWindowLocationHrefLink(methodInfo);

                //Wenn ein Href Link erstellt werden soll, dann kann es keinen ReturnType geben!
                if (proxyMethodInfo.CreateWindowLocationHrefLink)
                {
                    proxyMethodInfo.ReturnType = null;
                }

                if (methodInfo.DeclaringType != null)
                {
                    proxyMethodInfo.Namespace = methodInfo.DeclaringType.FullName;
                    proxyMethodInfo.MethodNameWithNamespace = string.Format("{0}.{1}", proxyMethodInfo.Namespace, methodInfo.Name);

                }

                proxyMethodInfos.Add(proxyMethodInfo);
            }

            return proxyMethodInfos;
        }
        /// <summary>
        /// Den passenden HttpCall zusammenbauen und prüfen ob Post oder Get verwendet werden soll
        /// Erstellt wird: post("/Home/LoadAll", data) oder get("/Home/LoadAll?userId=" + id)
        /// </summary>
        public string BuildHttpCall(ProxyMethodInfos methodInfo, ProxyBuilder proxyBuilder)
        {
            //Wie genau das Post oder Geht aussieht, hängt von den gewünschten Parametern ab.
            //Aktuell gehen wir von einer StandardRoute aus und wenn ein "id" in den Parametern ist, dann
            //Handelt es sich z.B. um den Letzten Parameter in der StandardRoute.
            //Beispiele:
            //.post("/Home/GetAutosByHerstellerId/" + id, message)
            //.post("/ControllerName/GetAutosByHerstellerId/", message)
            //get("/Home/GetSuccessMessage")
            //get("/Home/GetSuccessMessage/" + id + "?name=" + urlencodestring + "&test=2")

            //Prüfen ob ein complexer Typ verwendet wird.
            if (methodInfo.ProxyMethodParameterInfos.Count(p => p.IsComplexeType) == 0)
            {
                //Wenn über der Controller Action Post angegeben wurde, dann auch Post verwenden
                //obwohl kein komplexer Typ enthalten ist.
                if (ProxyBuilderHelper.HasAttribute(typeof(HttpPostAttribute), methodInfo.MethodInfo))
                {
                    if (proxyBuilder == ProxyBuilder.jQueryTypeScript || proxyBuilder == ProxyBuilder.jQueryJavaScript)
                    {
                        return BuildPostjQuery(methodInfo);
                    }

                    return BuildPostAngular(methodInfo, proxyBuilder);
                }

                //Kein Komplexer Typ also Get verwenden.
                return BuildGet(methodInfo);
            }

            if (proxyBuilder == ProxyBuilder.jQueryTypeScript || proxyBuilder == ProxyBuilder.jQueryJavaScript)
            {
                return BuildPostjQuery(methodInfo);
            }

            return BuildPostAngular(methodInfo, proxyBuilder);
        }
        /// <summary>
        /// Das passende HREF Template laden und die passenden TemplateString ersetzten.
        /// </summary>
        private string BuildHrefTemplate(ProxyMethodInfos methodInfos, ProxyControllerInfo controllerInfo, string suffix)
        {
            var functionTemplate = Factory.GetProxySettings().Templates.First(p => p.TemplateType == TemplateTypes.AngularJsWindowLocationHref).Template;

            //Den Methodennamen ersetzen - Der Servicename der aufgerufen werden soll.
            string functionCall = functionTemplate.Replace(ConstValuesTemplates.ControllerFunctionName, ProxyBuilderHelper.GetProxyFunctionName(methodInfos.MethodInfo.Name));
            //Parameter des Funktionsaufrufs ersetzen.
            functionCall = functionCall.Replace(ConstValuesTemplates.ServiceParamters, ProxyBuilderHelper.GetFunctionParameters(methodInfos.MethodInfo));
            //Href Call zusammenbauen und Parameter ersetzen
            functionCall = functionCall.Replace(ConstValuesTemplates.ServiceCallAndParameters, ProxyBuilderHttpCall.BuildHrefLink(methodInfos, ProxyBuilder.AngularJavaScript));
            //Den Servicenamen vor dem Prototype ersetzen.
            functionCall = functionCall.Replace(ConstValuesTemplates.ServiceName, ProxyBuilderHelper.GetServiceName(controllerInfo.ControllerNameWithoutSuffix, suffix, Factory.GetProxySettings().LowerFirstCharInFunctionName));
            return functionCall;
        }
        /// <summary>
        /// Rückgabe für Post erstellen für jQuery Calls
        /// </summary>
        /// <returns>Gibt den passenden POST Aufruf zurück</returns>
        private string BuildPostjQuery(ProxyMethodInfos infos)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(string.Format("ajax( {{ url : '{0}/{1}'", ProxyBuilderHelper.GetClearControllerName(infos.Controller), infos.MethodInfo.Name));

            builder.Append(ProxyBuilderHelper.BuildUrlParameterId(infos.ProxyMethodParameterInfos));
            builder.Append(ProxyBuilderHelper.BuildUrlParameter(infos.ProxyMethodParameterInfos));

            //Da auch ein Post ohne komplexen Typ aufgerufen werden kann über das "HttpPost" Attribut hier prüfen
            //ob ein komplexer Typ enthalten ist.
            if (infos.ProxyMethodParameterInfos.Any(p => p.IsComplexeType))
            {
                //Da es nur einen Complexen Typ geben darf pro Methodenaufruf, hier prüfen ob ein FileUpload dabei ist.
                if (infos.ProxyMethodParameterInfos.Any(p => p.IsFileUpload))
                {
                    //Achtung die "formData" Variable wird bei "#FunctionContent#" eingefügt
                    builder.Append(", data : formData, processData : false, contentType: false, type : \"POST\" })");
                }
                else
                {
                    //Standard Post
                    builder.Append(string.Format(", data : JSON.stringify({0}), type : \"POST\", contentType: \"application/json; charset=utf-8\" }})", infos.ProxyMethodParameterInfos.First(p => p.IsComplexeType).ParameterName));
                }
            }
            else
            {
                builder.Append("})");
            }

            return builder.ToString();
        }
        /// <summary>
        /// Rückgabe für Post erstellen für Angular Calls
        /// </summary>
        /// <returns>Gibt den passenden POST Aufruf zurück</returns>
        private string BuildPostAngular(ProxyMethodInfos infos, ProxyBuilder proxyBuilder)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(string.Format("post('{0}/{1}'", ProxyBuilderHelper.GetClearControllerName(infos.Controller), infos.MethodInfo.Name));

            builder.Append(ProxyBuilderHelper.BuildUrlParameterId(infos.ProxyMethodParameterInfos));
            builder.Append(ProxyBuilderHelper.BuildUrlParameter(infos.ProxyMethodParameterInfos));

            //Da auch ein Post ohne komplexen Typ aufgerufen werden kann über das "HttpPost" Attribut hier prüfen
            //ob ein komplexer Typ enthalten ist.
            if (infos.ProxyMethodParameterInfos.Any(p => p.IsComplexeType))
            {
                //Da es nur einen Complexen Typ geben darf pro Methodenaufruf, hier prüfen ob ein FileUpload dabei ist.
                if (infos.ProxyMethodParameterInfos.Any(p => p.IsFileUpload))
                {
                    if (proxyBuilder != ProxyBuilder.Angular2TypeScript)
                    {
                        //Achtung die "formData" Variable wird bei "#FunctionContent#" eingefügt
                        builder.Append(",formData, { transformRequest: angular.identity, headers: { 'Content-Type': undefined }})");
                    }
                    else
                    {
                        //für angular 2 muss hier nur FormData übergeben werden.
                        builder.Append(",formData)");
                    }
                }
                else
                {
                    //Standard Post
                    builder.Append(string.Format(",{0})", infos.ProxyMethodParameterInfos.First(p => p.IsComplexeType).ParameterName));
                }
            }
            else
            {
                builder.Append(")");
            }

            return builder.ToString();
        }
 /// <summary>
 /// Rückgabe für Get erstellen
 /// </summary>
 /// <returns>Gibt den passenden GET Aufruf in JavaScript zurück</returns>
 private string BuildGet(ProxyMethodInfos infos)
 {
     StringBuilder builder = new StringBuilder();
     //Keine Komplexen Typen, einfacher Get Aufruf.
     builder.Append(string.Format("get('{0}/{1}'", ProxyBuilderHelper.GetClearControllerName(infos.Controller), infos.MethodInfo.Name));
     builder.Append(ProxyBuilderHelper.BuildUrlParameterId(infos.ProxyMethodParameterInfos));
     builder.Append(ProxyBuilderHelper.BuildUrlParameter(infos.ProxyMethodParameterInfos));
     builder.Append(")");
     return builder.ToString();
 }
        public void BuildPost_IsComplexeType_False()
        {
            //Arrange
            var methodInfos = new ProxyMethodInfos();
            //Die MethodenInfos laden - können wir nicht Mocken!
            methodInfos.MethodInfo = TestClassType.GetMethod("OneComplexParamHttpPost");
            methodInfos.ProxyMethodParameterInfos.Add(new ProxyMethodParameterInfo() { IsComplexeType = false, ParameterName = "person" });

            //Mocken der passenden Infos
            MockBuildHelper.Setup(p => p.GetClearControllerName(It.IsAny<Type>())).Returns("Home");
            MockBuildHelper.Setup(p => p.BuildUrlParameterId(It.IsAny<List<ProxyMethodParameterInfo>>())).Returns(String.Empty);
            MockBuildHelper.Setup(p => p.BuildUrlParameter(It.IsAny<List<ProxyMethodParameterInfo>>())).Returns(" + '?name='+encodeURIComponent(name)");
            MockBuildHelper.Setup(p => p.HasAttribute(It.IsAny<Type>(), It.IsAny<MethodInfo>())).Returns(true);

            //Act
            var getParams = ProxyBuilderHttpCall.BuildHttpCall(methodInfos, ProxyBuilder.AngularTypeScript);

            //Assert
            Assert.AreEqual(getParams, "post('Home/OneComplexParamHttpPost' + '?name='+encodeURIComponent(name))");
        }
        /// <summary>
        /// Prüft ob ein FileUpload Parameter enthalten ist und wenn ja werden die passenden Formdaten erstellt
        /// Falls nicht wird einfach ein Leerstring zurückgegeben.
        /// </summary>
        public string GetFileUploadFormData(ProxyMethodInfos methodInfo)
        {
            if (methodInfo.ProxyMethodParameterInfos.Any(p => p.IsFileUpload))
            {
                var fileUploadParamName = methodInfo.ProxyMethodParameterInfos.First(p => p.IsFileUpload).ParameterName;

                string formData = string.Format("var formData = new FormData(); \r\n formData.append('{0}', {0}); \r\n", fileUploadParamName);
                return formData;
            }

            return String.Empty;
        }
        /// <summary>
        /// Das passende HREF Template laden und die passenden TemplateString ersetzten.
        /// </summary>
        private string BuildHrefTemplate(ProxyMethodInfos methodInfos)
        {
            var functionTemplate = Factory.GetProxySettings().Templates.First(p => p.TemplateType == TemplateTypes.Angular2TsWindowLocationHref).Template;

            //Den Methodennamen ersetzen - Der Servicename der aufgerufen werden soll.
            string functionCall = functionTemplate.Replace(ConstValuesTemplates.ControllerFunctionName, ProxyBuilderHelper.GetProxyFunctionName(methodInfos.MethodInfo.Name));
            //Parameter des Funktionsaufrufs ersetzen.
            functionCall = functionCall.Replace(ConstValuesTemplates.ServiceParamters, ProxyBuilderTypeHelper.GetFunctionParametersWithType(methodInfos.MethodInfo));
            //Href Call zusammenbauen und Parameter ersetzen
            functionCall = functionCall.Replace(ConstValuesTemplates.ServiceCallAndParameters, ProxyBuilderHttpCall.BuildHrefLink(methodInfos, ProxyBuilder.Angular2TypeScript));
            return functionCall;
        }