0

我正在使用 asp:ScriptManager 从 javascript 调用我的 webmethods。现在我迁移到 TypeScript 并希望我的 WebMethods 和 DTO 定义可以从 TypeScript 中使用。我进行了搜索,但找不到任何执行此操作的内容(建议除外)。

现在我正在实现一个代码生成工具,它采用 wsdl 并生成打字稿类型。完成后我会在这里分享它,但与此同时,如果你知道任何可以做到这一点的工具,我会很高兴听到。

提前致谢。


这就是我从 javascipt 调用 webmethods 的方式。

1) web.config

<system.serviceModel>
<services>
  <service name="Services.MyService" behaviorConfiguration="metadataBehavior">
    <endpoint binding="basicHttpBinding" contract="Services.MyService"/>
    <endpoint address="/ajax" behaviorConfiguration="Services.MyServiceAspNetAjaxBehavior" binding="webHttpBinding" contract="Services.MyService"/>
  </service>
</services>
<behaviors>
  <endpointBehaviors>
    <behavior name="Services.MyServiceAspNetAjaxBehavior">
      <enableWebScript />
    </behavior>
  </endpointBehaviors>
</behaviors>
</system.serviceModel>

2) 默认.aspx

<form id="form1" runat="server">
    <asp:ScriptManager ID="Scriptmanager1" runat="server">
        <Services>
            <asp:ServiceReference Path="~/MyService.svc/ajax" />
        </Services>
    </asp:ScriptManager>
</form>

3) 一些文件.js

<script>
    MyService.SomeMethod(someParameter1, someParameter2, function(result) {
        alert("Success: " + result);
    }, function(err){
        alert("Error: " + err);
    });

</script>

我可以在 ~/MyService.svc/ajax/jsdebug 上看到一个 js 文件,该文件具有调用我的 web 服务的功能

4

1 回答 1

0

好吧,这是我编写和使用的代码,但是您需要为自己的 wsdl 更改一些参数。反馈是appriciated。

此外,如果有人升级并将其制成博客文章,那会很棒(我没有博客)我想很多人会需要它,这可以节省我们项目的大量时间并整理东西。

顺便说一句,我在 Linqpad 中运行此代码。这就是为什么方法不是静态的,并且在 Main() 的最后一行有一个 object.Dump() 调用

void Main()
{
    var svcUrl = "http://localhost:12345/MyService.svc";
    var declaration = "declare var MyService: MyServiceClient;";
    var koRef = "/// <reference path=\"../../Scripts/typings/knockout.mapping/knockout.mapping.d.ts" +
    "\" />\r\n/// <reference path=\"../../Scripts/typings/knockout/knockout.d.ts\" />";


    TypeScriptWebServiceAndKnockOutTypings(svcUrl, declaration, koRef).Dump();
}


string TypeScriptWebServiceAndKnockOutTypings(string svcUrl, string declaration, string koRef)
{
    var outputPath = @"d:\output";

    File.Delete(outputPath + ".cs");
    File.Delete(outputPath + ".dll");
    Process.Start(@"C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\x64\svcutil.exe",  " /language:cs /out:" + outputPath + ".cs " + svcUrl).WaitForExit();
    Process.Start(@"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe", " /t:library /out:"+ outputPath + ".dll  "+ outputPath + ".cs").WaitForExit();

    var a = Assembly.LoadFile(outputPath + ".dll");

    var sbEnums = new StringBuilder();
    var sbClasses = new StringBuilder();

    #region types conversions

    var dictTypesNormal = new Dictionary<Type, string>();
    dictTypesNormal.Add(typeof(Int32), "number");
    dictTypesNormal.Add(typeof(UInt32), "number");
    dictTypesNormal.Add(typeof(Int64), "number");
    dictTypesNormal.Add(typeof(UInt64), "number");
    dictTypesNormal.Add(typeof(float), "number");
    dictTypesNormal.Add(typeof(double), "number");
    dictTypesNormal.Add(typeof(bool), "bool");
    dictTypesNormal.Add(typeof(string), "string");
    dictTypesNormal.Add(typeof(Object), "any");
    dictTypesNormal.Add(typeof(DateTime), "Date");

    var dictTypesKnockout = new Dictionary<Type, string>();
    dictTypesKnockout.Add(typeof(Int32), "KnockoutObservableNumber");
    dictTypesKnockout.Add(typeof(UInt32), "KnockoutObservableNumber");
    dictTypesKnockout.Add(typeof(Int64), "KnockoutObservableNumber");
    dictTypesKnockout.Add(typeof(UInt64), "KnockoutObservableNumber");
    dictTypesKnockout.Add(typeof(float), "KnockoutObservableNumber");
    dictTypesKnockout.Add(typeof(double), "KnockoutObservableNumber");
    dictTypesKnockout.Add(typeof(bool), "KnockoutObservableBool");
    dictTypesKnockout.Add(typeof(string), "KnockoutObservableString");
    dictTypesKnockout.Add(typeof(Object), "KnockoutObservableAny");
    dictTypesKnockout.Add(typeof(DateTime), "KnockoutObservableDate");

    var classNames = a.DefinedTypes.Where(t => !t.IsEnum).Select(t=>t.Name).ToList();
    var enumNames = a.DefinedTypes.Where(t => t.IsEnum).Select(t=>t.Name).ToList();

    #region get type name

    Func<Type, string> getTypeNameNormal = t => {
        if(dictTypesNormal.ContainsKey(t)) 
            return dictTypesNormal[t];

        if(classNames.Contains(t.Name.Replace("[]", ""))) 
            return t.Name;

        if(enumNames.Contains(t.Name.Replace("[]", ""))) 
            return "Enum" + t.Name;

        throw new Exception(string.Format("Unknown type [{0}]", t.Name));
    };

    Func<Type, string> getTypeNameKnockout = t => {
        if(dictTypesKnockout.ContainsKey(t)) 
            return dictTypesKnockout[t];

        if(classNames.Contains(t.Name.Replace("[]", ""))) 
            return t.Name + "_KnockoutMapped";

        if(enumNames.Contains(t.Name.Replace("[]", ""))) 
            return "KnockoutObservableEnum" + t.Name + "EnumMember";

        throw new Exception(string.Format("Unknown type [{0}]", t.Name));
    };

    #endregion

    #region convert field 

    Func<string, Type, string> convertFieldNormal = null; convertFieldNormal = (pName, f) => {

        // void
        if(f == typeof(void)) 
            return "";

        // array
        if(f.IsArray)
            return string.Format("{0}{1}[]", pName, convertFieldNormal("", f.GetElementType()));

        // property
        if(!f.IsGenericType) 
            return string.Format("{0}: {1}", pName, getTypeNameNormal(f));

        // nullable
        if(f.GetGenericTypeDefinition() == typeof(Nullable<>)) 
            return string.Format("{0}: {1}", pName, getTypeNameNormal(f.GetGenericArguments()[0]));

        // dictionaries
        if(f.GetGenericTypeDefinition().ToString().Contains("Dictionary")) 
            return string.Format("{0}: {{ {1}; {2}; }}[]", pName, convertFieldNormal("Key", f.GetGenericArguments()[0]), convertFieldNormal("Value", f.GetGenericArguments()[1]));

        throw new Exception(string.Format("Unknown generic type [{0}] for property {1}", f.Name, pName));
    };

    Func<string, Type, string> convertFieldKnockout = null; convertFieldKnockout = (pName, f) => {

        // void
        if(f == typeof(void)) 
            return "";

        // array
        if(f.IsArray)
            return string.Format("{0}{1}[]", pName, convertFieldKnockout("", f.GetElementType()));

        // property
        if(!f.IsGenericType) 
            return string.Format("{0}: {1}", pName, getTypeNameKnockout(f));

        // nullable
        if(f.GetGenericTypeDefinition() == typeof(Nullable<>)) 
            return string.Format("{0}: {1}", pName, getTypeNameKnockout(f.GetGenericArguments()[0]));

        // dictionaries
        if(f.GetGenericTypeDefinition().ToString().Contains("Dictionary")) 
            return string.Format("{0}: {{ {1}; {2}; }}[]", pName, convertFieldKnockout("Key", f.GetGenericArguments()[0]), convertFieldKnockout("Value", f.GetGenericArguments()[1]));

        throw new Exception(string.Format("Unknown generic type [{0}] for property {1}", f.Name, pName));
    };

    #endregion

    #endregion

    #region enums

    foreach (var e in a.DefinedTypes.Where(t => t.IsEnum))
    {
        #region enum definition
        sbEnums.AppendLine(string.Format("enum Enum{0} {{", e.Name));

        sbEnums.AppendLine(string.Format("\t{0} = {1},", "Tümü", -1)); 

        foreach (var v in Enum.GetValues(e))
        {
            sbEnums.AppendLine(string.Format("\t{0} = {1},", v.ToString(), (int)v)); 
        }

        sbEnums.AppendLine("}");
        #endregion

        #region knockout

        sbEnums.AppendLine(string.Format(
            @"interface KnockoutObservable{0} extends KnockoutObservableBase {{
                (): {0};
                (value: {0}): void;

                subscribe(callback: (newValue: {0}) => void , target?: any, topic?: string): KnockoutSubscription;
                notifySubscribers(valueToWrite: {0}, topic?: string);
            }}", "Enum" + e.Name + "EnumMember"));

        #endregion

        #region enum member

        sbEnums.AppendLine(string.Format(
            @"class Enum{0}EnumMember {{
                constructor(public Key: Enum{0}, public Value: string) {{ }};
                public toString() {{ return this.Value }};
              }}", e.Name));

        #endregion

        #region combobox definition
        sbEnums.AppendLine(string.Format("var {0}s: Enum{0}EnumMember[] = [", e.Name));

        sbEnums.AppendLine(string.Format("\t new Enum{0}EnumMember(Enum{0}.{1}, \"{1}\"),", e.Name, "Tümü")); 

        foreach (var v in Enum.GetValues(e))
        {
            sbEnums.AppendLine(string.Format("\t new Enum{0}EnumMember(Enum{0}.{1}, \"{1}\"),", e.Name, v.ToString())); 
        }

        sbEnums.AppendLine("];");
        #endregion

        //public OnayDurumlari = ko.observable([{ Key: 3, Value: "Tümü" }, { Key: 0, Value: "Onay Bekliyor" }, { Key: 1, Value: "Onaylı" }, { Key: 2, Value: "Red" }]); 

        sbEnums.AppendLine();
    }

    #endregion

    #region classes

    #region find classes & methods

    var classes =  (from t in a.DefinedTypes
                    where t.IsEnum == false
                    let methods = (from m in t.GetMethods()
                                    where !m.IsSpecialName 
                                    && m.IsFinal 
                                    && m.IsVirtual 
                                    && m.IsHideBySig 
                                    && m.IsSecurityCritical 
                                    && !m.Name.EndsWith("Async")
                                    select m)
                    where t.DeclaredProperties.Any()
                        || methods.Any()
                    select new
                    {
                        t.Name,
                        t.DeclaredProperties,
                        methods,
                    });

    #endregion

    foreach (var t in classes)
    {
        #region interface definition

        sbClasses.AppendLine(string.Format("{1} {0} {{", t.Name, t.DeclaredProperties.Any() ? "class" : "interface"));

        foreach (var p in t.DeclaredProperties)
        {
            if(p.Name == "ExtensionData") continue;
            var f = p.GetGetMethod().ReturnType;

            sbClasses.AppendLine(string.Format("\t{0};", convertFieldNormal(p.Name, f)));
        }

        #region methods

        foreach (var m in t.methods)
        {
            sbClasses.AppendLine(string.Format("\t{0}({1}Success: ({2}) => void, Fail?: (err: Sys$Net$WebServiceError) => void ) : void;", 
                m.Name, 
                string.Concat(m.GetParameters().Select(p => convertFieldNormal(p.Name, p.ParameterType) + ", ")),
                convertFieldNormal("result", m.ReturnType)));
        }

        #endregion

        sbClasses.AppendLine("}");

        #endregion

        #region knockout

        if(t.DeclaredProperties.Any())
        {
            sbClasses.AppendLine(string.Format(@"
                interface KnockoutObservable{0} extends KnockoutObservableBase {{
                    (): {0};
                    (value: {0}): void;

                    subscribe(callback: (newValue: {0}) => void , target?: any, topic?: string): KnockoutSubscription;
                    notifySubscribers(valueToWrite: {0}, topic?: string);
                }}", t.Name));
//  
//          sbClasses.AppendLine(string.Format(@"
//              interface KnockoutObservableStatic {{
//                  (value: {0}): KnockoutObservable{0};
//                  new (value: {0}): KnockoutObservable{0};
//              }}", t.Name));

            #region KnockoutObservableArray

            sbClasses.AppendLine(string.Format(
                @"interface {0}_KnockoutObservableArray extends KnockoutObservableArrayFunctions {{
                    (): {0}_KnockoutMapped[];
                    (value: {0}_KnockoutMapped[]): void;

                    subscribe(callback: (newValue: {0}_KnockoutMapped[]) => void, target?:any, topic?: string): KnockoutSubscription;
                    notifySubscribers(valueToWrite: {0}_KnockoutMapped[], topic?: string);
                }}", t.Name));

            #endregion

            #region _KnockoutMapped
            sbClasses.AppendLine(string.Format("interface {0}_KnockoutMapped {{", t.Name));

            foreach (var p in t.DeclaredProperties)
            {
                if(p.Name == "ExtensionData") continue;
                var f = p.GetGetMethod().ReturnType;

                sbClasses.AppendLine(string.Format("\t{0};", convertFieldKnockout(p.Name, f)));
            }               
            sbClasses.AppendLine("}");
            #endregion

        }
        #endregion

        sbClasses.AppendLine();
    }

    #endregion

    #region knockout

    var sbKnockout = new StringBuilder();

    #region mapper
    sbKnockout.AppendLine("module Mapper {");
    classes.Where(c=>c.DeclaredProperties.Any()).ToList().ForEach(c=>{
        sbKnockout.AppendLine(string.Format("\texport function fromJs_{0}(r : {0}) : {0}_KnockoutMapped {{return ko.mapping.fromJS(r);}}", c.Name));
        sbKnockout.AppendLine(string.Format("\texport function toJs_{0}(r : {0}_KnockoutMapped) : {0} {{return ko.mapping.toJS(r);}}", c.Name));
        sbKnockout.AppendLine(string.Format("\texport function fromJsArray_{0}(r : {0}[]) : {0}_KnockoutMapped[] {{return r.map(k => ko.mapping.fromJS(k));}}", c.Name));
        sbKnockout.AppendLine(string.Format("\texport function toJsArray_{0}(r : {0}_KnockoutMapped[]) : {0}[] {{return r.map(k => ko.mapping.toJS(k));}}", c.Name));
    });
    sbKnockout.AppendLine("}");
    sbKnockout.AppendLine();
    #endregion

    #region knockout definitions
    sbKnockout.AppendLine("declare var ko;");
    dictTypesKnockout.Select(k=>k.Value).Distinct().ToList().ForEach(k=>{
        sbKnockout.AppendLine(string.Format("interface {0} {{}}", k));
    });
    sbKnockout.AppendLine("interface KnockoutSubscription {}");
    sbKnockout.AppendLine("interface KnockoutObservableArrayFunctions {}");
    sbKnockout.AppendLine();
    #endregion

    #endregion

    return koRef 
         + "interface Sys$Net$WebServiceError {_timedOut: bool;_message: string;_stackTrace: string;_exceptionType: string;_errorObject: {ExceptionDetail: {HelpLink: any; InnerException: any; Message: string; StackTrace: string;Type: string;};ExceptionType: string;Message: string;StackTrace: string;};}\r\n\r\n"
         + sbEnums.ToString()
         + sbClasses.ToString()
         + sbKnockout
         + declaration;
}
于 2013-05-12T11:28:06.823 回答