Skip to content

Instantly share code, notes, and snippets.

@KatsuYuzu
Last active April 23, 2016 07:37
Show Gist options
  • Save KatsuYuzu/99e5222453070e6cb61e1a63f9cb3f01 to your computer and use it in GitHub Desktop.
Save KatsuYuzu/99e5222453070e6cb61e1a63f9cb3f01 to your computer and use it in GitHub Desktop.
ASP.NET WebAPI 体験記 #clrh99 で話した割り切り WebAPI に対応したクライアント自動生成 T4
/* tslint:disable */
namespace App.WebApi {
"use strict";
//#region infrastructure
angular.module("webApiClient", [])
.provider("webApiClientHandler", [function () {
this.defaultRequestHeaders = true;
this.webApiClientHandlerFactory = function ($http: ng.IHttpService) {
let handler = new Core.WebApiClientHandler($http);
return handler;
};
this.$get = ["$http", this.webApiClientHandlerFactory];
}])
.provider("webapi", [function () {
this.webApiClientFactory =
function ($q: ng.IQService, rootEndPoint: string, webApiClientHandler: Core.WebApiClientHandler) {
let client = new WebApiClient($q, rootEndPoint, webApiClientHandler);
client.timeout = this.timeout;
Object.keys(this.defaultRequestHeaders || {}).forEach(
(x: string) => {
client.defaultRequestHeaders[x] = this.defaultRequestHeaders[x];
});
return client;
};
this.$get = [
"$q", "webApiClientHandler",
function ($q: ng.IQService, webApiClientHandler: Core.WebApiClientHandler) {
return this.webApiClientFactory($q, this.rootEndPoint, webApiClientHandler);
}];
}]);
export namespace Core {
/**
* Use the annotation of "webApiClientHandlerProvider".
*/
export interface IWebApiClientHandlerProvider {
webApiClientHandlerFactory: ($http: ng.IHttpService) => WebApiClientHandler;
}
/**
* Use the annotation of "webapiProvider".
*/
export interface IWebApiClientProvider {
rootEndPoint: string;
defaultRequestHeaders: { [key: string]: string };
timeout: number;
webApiClientFactory: ($q: ng.IQService, rootEndPoint: string, $http: ng.IHttpService) => WebApiClientBase;
}
export interface IHttpResponseTransformer<T> {
(data: any, headersGetter: ng.IHttpHeadersGetter, status: number): T;
}
export class ArgumentError extends Error {
constructor(message: string = "Value does not fall within the expected range.", paramName?: string) {
super();
this.name = "ArgumentError";
this.message = message + (paramName ? ": " + paramName : "");
}
}
export class ArgumentNullError extends ArgumentError {
constructor(paramName?: string, message: string = "Value cannot be null.") {
super(message, paramName);
this.name = "ArgumentNullError";
}
}
export class ArgumentOutOfRangeError extends ArgumentError {
constructor(paramName?: string, message: string = "Specified argument was out of the range of valid values.") {
super(message, paramName);
this.name = "ArgumentOutOfRangeError";
}
}
export class WebApiClientHandler {
constructor(private $http: ng.IHttpService) {
if (!$http) {
throw new ArgumentNullError("$http");
}
}
protected serializeToFormData(data: any): string {
return Object.keys(data || {})
.map((x: string) => {
let value = data[x];
if (value === void 0 || value === null) {
value = "";
}
return encodeURIComponent(x) + "=" + encodeURIComponent(value);
})
.join("&");
}
public post<T>(
url: string,
data?: any,
timeout?: number | ng.IPromise<void>,
requestHeaders?: ng.IHttpRequestConfigHeaders,
transformResponse?: IHttpResponseTransformer<T>,
responseType?: string): ng.IPromise<T> {
if (!url) {
throw new ArgumentNullError("url");
}
let config = <ng.IRequestShortcutConfig>{
timeout: timeout,
headers: requestHeaders,
responseType: responseType || "json",
transformResponse: transformResponse
};
return this.$http.post(url, data, config);
}
}
export class CancellationTokenSource {
constructor(private deferred: ng.IDeferred<void>) {
if (!deferred) {
throw new ArgumentNullError("deferred");
}
}
public get token(): ng.IPromise<void> {
return this.deferred.promise;
}
public cancel(): void {
this.deferred.resolve();
}
}
export class WebApiClientBase {
constructor(private $q: ng.IQService, private rootEndPoint: string, private innerHandler: WebApiClientHandler) {
if (!$q) {
throw new ArgumentNullError("$q");
}
if (!rootEndPoint) {
throw new ArgumentNullError("rootEndPoint");
}
if (!innerHandler) {
throw new ArgumentNullError("innerHandler");
}
this.$q = $q;
this.rootEndPoint = rootEndPoint.replace(/\/$/, "");
if (!this.rootEndPoint) {
throw new ArgumentOutOfRangeError("rootEndPoint");
}
this.innerHandler = innerHandler;
this._defaultRequestHeaders = {
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest"
};
}
private _timeout: number;
public get timeout(): number {
return this._timeout;
}
public set timeout(value: number) {
if (value <= 0) {
throw new ArgumentOutOfRangeError();
}
this._timeout = value;
}
private _defaultRequestHeaders: { [key: string]: string };
public get defaultRequestHeaders(): { [key: string]: string } {
return this._defaultRequestHeaders;
};
protected post<T>(
method: string,
data?: any,
cancellationToken?: ng.IPromise<void>,
transformResponse?: IHttpResponseTransformer<T>,
responseType?: string): ng.IPromise<T> {
if (!method) {
throw new ArgumentNullError("method");
}
return this.innerHandler.post(
this.rootEndPoint + method,
data,
cancellationToken || this.timeout,
this.defaultRequestHeaders,
transformResponse,
responseType)
.then((x: any) => x.data);
}
public createCancellationTokenSource(): CancellationTokenSource {
return new CancellationTokenSource(this.$q.defer<void>());
};
protected validStatusCode(status: number): boolean {
return 200 <= status && status <= 299;
}
protected parseJSON(json: any): any {
return typeof json === "string"
? JSON.parse(json)
: json;
}
}
}
//#endregion
export class Person {
constructor(json?: any) {
this.id = json.Id;
this.name = json.Name;
}
public id: number;
public name: string;
}
export namespace Controllers {
export interface ISampleController {
getPiyo(cancellationToken?: ng.IPromise<void>): ng.IPromise<Person>;
}
}
/**
* Provides webapi methods.
* Use the annotation of "webapi".
*/
export class WebApiClient extends Core.WebApiClientBase {
constructor($q: ng.IQService, rootEndPoint: string, innerHandler: Core.WebApiClientHandler) {
super($q, rootEndPoint, innerHandler);
}
private _sample: Controllers.ISampleController;
/**
* Provides methods of SampleController.
*/
public get sample(): Controllers.ISampleController {
if (!this._sample) {
this._sample = {
getPiyo: this.sampleGetPiyo.bind(this)
};
}
return this._sample;
}
protected sampleGetPiyo(cancellationToken?: ng.IPromise<void>): ng.IPromise<Person> {
let data = {};
return this.post<Person>("/Sample/GetPiyo", data, cancellationToken,
(data: any, headersGetter: ng.IHttpHeadersGetter, status: number) => {
if (!this.validStatusCode(status)) {
return data;
}
let json = this.parseJSON(data);
return json ? new Person(json) : null;
});
}
}
}
/* tslint:enable */
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Threading" #>
<#@ import namespace="System.Threading.Tasks" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension="ts" encoding="utf-8" #>
<#@ assembly name="$(SolutionDir)\WebApplication4\bin\WebApplication4.dll" #>
<#
// ------------- T4 Configuration ------------- //
// 1. Set ApiController assemblies(and all dependency) path to above #@ assembly name # directive
// 2. Set Namespace
var namespaceName = "App.WebApi";
// 3. Set ModuleName & ClientName(register to angular)
var moduleName = "webApiClient";
var clientName = "webapi";
// 3. Set allow upper camel case json(ex: true: json.PersonName, false: json.personName)
var allowUpperCamelJson = true;
// ----------End T4 Configuration ------------- //
var @typeMap = new Dictionary<string, string>()
{
{"String", "string"},
{"DateTime", "Date"},
{"Int16", "number"},
{"Int32", "number"},
{"Int64", "number"},
{"Single", "number"},
{"Double", "number"},
{"Decimal", "number"},
{"Boolean", "boolean"},
{"Void", "void"},
{"HttpResponseMessage", "ArrayBuffer"},
{"CancellationToken", "ng.IPromise<void>"}
};
Type[] complexTypes = {};
Type[] enumTypes = {};
Type[] parameterTypes = {};
Func<string, string> SwapType = (string name) =>
{
return typeMap.ContainsKey(name) ? typeMap[name]
: complexTypes.Any(x => x.Name == name) || enumTypes.Any(x => x.Name == name) ? name
: parameterTypes.Any(x => x.Name == name) ? "I" + name
: "any";
};
Func<Type, bool> IsEnumerableType = (Type t) =>
{
return t != typeof(string)
&& ((t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>))
|| t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable<>)));
};
Func<Type, string> BeautifyType = null;
BeautifyType = (Type t) =>
{
if (t.IsArray) return BeautifyType(t.GetElementType()) + "[]";
if (!t.IsGenericType) return SwapType(t.Name);
if (t.GetGenericTypeDefinition() == typeof(Nullable<>)) return BeautifyType(t.GetGenericArguments()[0]);
if (IsEnumerableType(t)) return BeautifyType(t.GetGenericArguments()[0]) + "[]";
var innerFormat = string.Join(", ", t.GetGenericArguments().Select(x => BeautifyType(x)));
return Regex.Replace(t.GetGenericTypeDefinition().Name, @"`.+$", "") + "<" + innerFormat + ">";
};
Func<Type, Type> UnWrapNullableOrSelf = (Type t) =>
{
return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>) ? t.GetGenericArguments()[0] : t;
};
Func<Type, Type> UnWrapEnumerableOrSelf = (Type t) =>
{
return t.IsArray ? t.GetElementType()
: t.IsGenericType && IsEnumerableType(t) ? t.GetGenericArguments()[0] : t;
};
Func<Type, bool> IsComplexType = (Type t) =>
{
var beautifyType = BeautifyType(t);
return typeMap.Values.All(x => x != beautifyType && x + "[]" != beautifyType);
};
Func<Type, IEnumerable<Type>> FindComplexTypes = null;
FindComplexTypes = (Type t) =>
{
var complexTypeProperties = t.GetProperties()
.Where(x => x.CanRead)
.Select(x => x.PropertyType)
.Select(x => UnWrapEnumerableOrSelf(x))
.Select(x => UnWrapNullableOrSelf(x))
.Where(x => IsComplexType(x))
.Where(x => x != t)
.Where(x => x != typeof(object))
.SelectMany(x => FindComplexTypes(x))
.ToArray();
if(complexTypeProperties.Any())
{
return (new Type[]{t}).Concat(complexTypeProperties);
}
else
{
return new Type[]{t};
}
};
Func<string, string> ToLowerCamelCase = (string value) =>
{
return Regex.Replace(value, "^(.)(.*)", x => x.Groups[1].Value.ToLower() + x.Groups[2].Value);
};
Func<Type, bool> ShouldCreateInstance = (Type t) =>
{
var beautifyType = BeautifyType(t).TrimEnd('[', ']');
return beautifyType == "Date" || complexTypes.Any(x => x.Name == beautifyType);
};
var @typeFromAssemblies = System.AppDomain.CurrentDomain
.GetAssemblies()
.Where(x => !Regex.IsMatch(x.GetName().Name, "^(mscorlib|System|EnvDTE)$"))
.SelectMany(x => x.GetTypes())
.Where(x => x != null && x.FullName != "System.Web.Http.ApiController");
var @ignoreMethods = new HashSet<string> { "Equals", "GetHashCode", "GetType", "ToString" };
var @controllerTypes = typeFromAssemblies
.Where(x =>
{
while (x != typeof(object) && x != null)
{
if (x.FullName == "System.Web.Http.ApiController") return true;
x = x.BaseType;
}
return false;
})
.Select(x =>
{
var actions = x.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
.Where(methodInfo => !(methodInfo.IsSpecialName && (methodInfo.Name.StartsWith("set_") || methodInfo.Name.StartsWith("get_"))))
.Where(methodInfo => !ignoreMethods.Contains(methodInfo.Name))
.Select(methodInfo =>
{
var retType = methodInfo.ReturnType;
var returnType =
(retType == typeof(Task)) ? typeof(void)
: (retType.IsGenericType && retType.GetGenericTypeDefinition() == typeof(Task<>)) ? retType.GetGenericArguments()[0]
: retType;
return new
{
Info = methodInfo,
ReturnType = returnType,
Parameters = methodInfo.GetParameters()
.Select(paramInfo => new
{
Info = paramInfo,
ParameterType = paramInfo.ParameterType
})
.ToArray()
};
})
.ToArray();
return new
{
Type = x,
Actions = actions
};
})
.ToArray();
var @shouldDefineReturnTypes = controllerTypes
.SelectMany(x => x.Actions)
.Select(x => x.ReturnType)
.Select(x => UnWrapEnumerableOrSelf(x))
.Select(x => UnWrapNullableOrSelf(x))
.Where(x => IsComplexType(x))
.SelectMany(x => FindComplexTypes(x))
.ToArray();
var @shouldDefineParameterTypes = controllerTypes
.SelectMany(x => x.Actions)
.SelectMany(x => x.Parameters)
.Select(x => x.ParameterType)
.Select(x => UnWrapEnumerableOrSelf(x))
.Select(x => UnWrapNullableOrSelf(x))
.Where(x => IsComplexType(x))
.SelectMany(x => FindComplexTypes(x))
.ToArray();
complexTypes = shouldDefineReturnTypes
.Concat(shouldDefineReturnTypes)
.Where(x => x.IsClass)
.Distinct()
.ToArray();
enumTypes = shouldDefineReturnTypes
.Concat(shouldDefineParameterTypes)
.Where(x => x.IsEnum)
.Distinct()
.ToArray();
parameterTypes = shouldDefineParameterTypes
.Where(x => x.IsClass)
.Distinct()
.ToArray();
var controllers = controllerTypes
.Select(x =>
{
var actions = x.Actions
.Select(action =>
{
var parameters = action.Parameters
.Select(p => new
{
p.Info.Name,
p.Info.ParameterType,
p.Info.IsOptional,
p.Info.DefaultValue,
IsBoolean = p.Info.ParameterType == typeof(Boolean),
IsCancellationToken = false,
})
.Concat(new[]{new
{
Name = "cancellationToken",
ParameterType = typeof(CancellationToken),
IsOptional = true,
DefaultValue = (object)default(CancellationToken),
IsBoolean = false,
IsCancellationToken = true,
}})
.ToArray();
var parameterString = string.Join(", ", parameters.Select(p =>
{
return p.Name + (p.IsOptional ? "?" : "") + ": " + BeautifyType(p.ParameterType);
}));
var parameterStringWithOptional = string.Join(", ", parameters.Select(p =>
{
var withoutValue = p.Name + (p.IsOptional ? "?" : "") + ": " + BeautifyType(p.ParameterType);
if (p.IsOptional)
{
var withValueBase = p.Name + ": " + BeautifyType(p.ParameterType);
return (
(p.DefaultValue == null) ? withoutValue
: (p.DefaultValue is string) ? withValueBase + " = \"" + p.DefaultValue + "\""
: (p.DefaultValue is CancellationToken) ? withoutValue
: (p.ParameterType.IsEnum) ? withValueBase + " = " + p.ParameterType.Name + "." + p.DefaultValue.ToString()
: withValueBase + " = " + p.DefaultValue.ToString().ToLower());
} else {
return withoutValue;
}
}));
return new
{
Name = action.Info.Name,
ReturnType = action.ReturnType,
IsReturnBinary = action.ReturnType.Name == "HttpResponseMessage",
IsComplexTypeParameter = parameterTypes.Any(p => p == parameters.First().ParameterType),
Parameters = parameters,
ParameterString = parameterString,
ParameterStringWithOptional = parameterStringWithOptional
};
})
.ToArray();
return new
{
Name = Regex.Replace(x.Type.Name, "^(.*)Controller$", "$1"),
InterfaceName = "I" + x.Type.Name,
Actions = actions
};
})
.ToArray();
#>
/* tslint:disable */
namespace <#= namespaceName #> {
"use strict";
//#region infrastructure
angular.module("<#= moduleName #>", [])
.provider("webApiClientHandler", [function () {
this.defaultRequestHeaders = true;
this.webApiClientHandlerFactory = function ($http: ng.IHttpService) {
let handler = new Core.WebApiClientHandler($http);
return handler;
};
this.$get = ["$http", this.webApiClientHandlerFactory];
}])
.provider("<#= clientName #>", [function () {
this.webApiClientFactory =
function ($q: ng.IQService, rootEndPoint: string, webApiClientHandler: Core.WebApiClientHandler) {
let client = new WebApiClient($q, rootEndPoint, webApiClientHandler);
client.timeout = this.timeout;
Object.keys(this.defaultRequestHeaders || {}).forEach(
(x: string) => {
client.defaultRequestHeaders[x] = this.defaultRequestHeaders[x];
});
return client;
};
this.$get = [
"$q", "webApiClientHandler",
function ($q: ng.IQService, webApiClientHandler: Core.WebApiClientHandler) {
return this.webApiClientFactory($q, this.rootEndPoint, webApiClientHandler);
}];
}]);
export namespace Core {
/**
* Use the annotation of "webApiClientHandlerProvider".
*/
export interface IWebApiClientHandlerProvider {
webApiClientHandlerFactory: ($http: ng.IHttpService) => WebApiClientHandler;
}
/**
* Use the annotation of "<#= clientName #>Provider".
*/
export interface IWebApiClientProvider {
rootEndPoint: string;
defaultRequestHeaders: { [key: string]: string };
timeout: number;
webApiClientFactory: ($q: ng.IQService, rootEndPoint: string, $http: ng.IHttpService) => WebApiClientBase;
}
export interface IHttpResponseTransformer<T> {
(data: any, headersGetter: ng.IHttpHeadersGetter, status: number): T;
}
export class ArgumentError extends Error {
constructor(message: string = "Value does not fall within the expected range.", paramName?: string) {
super();
this.name = "ArgumentError";
this.message = message + (paramName ? ": " + paramName : "");
}
}
export class ArgumentNullError extends ArgumentError {
constructor(paramName?: string, message: string = "Value cannot be null.") {
super(message, paramName);
this.name = "ArgumentNullError";
}
}
export class ArgumentOutOfRangeError extends ArgumentError {
constructor(paramName?: string, message: string = "Specified argument was out of the range of valid values.") {
super(message, paramName);
this.name = "ArgumentOutOfRangeError";
}
}
export class WebApiClientHandler {
constructor(private $http: ng.IHttpService) {
if (!$http) {
throw new ArgumentNullError("$http");
}
}
protected serializeToFormData(data: any): string {
return Object.keys(data || {})
.map((x: string) => {
let value = data[x];
if (value === void 0 || value === null) {
value = "";
}
return encodeURIComponent(x) + "=" + encodeURIComponent(value);
})
.join("&");
}
public post<T>(
url: string,
data?: any,
timeout?: number | ng.IPromise<void>,
requestHeaders?: ng.IHttpRequestConfigHeaders,
transformResponse?: IHttpResponseTransformer<T>,
responseType?: string): ng.IPromise<T> {
if (!url) {
throw new ArgumentNullError("url");
}
let config = <ng.IRequestShortcutConfig>{
timeout: timeout,
headers: requestHeaders,
responseType: responseType || "json",
transformResponse: transformResponse
};
return this.$http.post(url, data, config);
}
}
export class CancellationTokenSource {
constructor(private deferred: ng.IDeferred<void>) {
if (!deferred) {
throw new ArgumentNullError("deferred");
}
}
public get token(): ng.IPromise<void> {
return this.deferred.promise;
}
public cancel(): void {
this.deferred.resolve();
}
}
export class WebApiClientBase {
constructor(private $q: ng.IQService, private rootEndPoint: string, private innerHandler: WebApiClientHandler) {
if (!$q) {
throw new ArgumentNullError("$q");
}
if (!rootEndPoint) {
throw new ArgumentNullError("rootEndPoint");
}
if (!innerHandler) {
throw new ArgumentNullError("innerHandler");
}
this.$q = $q;
this.rootEndPoint = rootEndPoint.replace(/\/$/, "");
if (!this.rootEndPoint) {
throw new ArgumentOutOfRangeError("rootEndPoint");
}
this.innerHandler = innerHandler;
this._defaultRequestHeaders = {
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest"
};
}
private _timeout: number;
public get timeout(): number {
return this._timeout;
}
public set timeout(value: number) {
if (value <= 0) {
throw new ArgumentOutOfRangeError();
}
this._timeout = value;
}
private _defaultRequestHeaders: { [key: string]: string };
public get defaultRequestHeaders(): { [key: string]: string } {
return this._defaultRequestHeaders;
};
protected post<T>(
method: string,
data?: any,
cancellationToken?: ng.IPromise<void>,
transformResponse?: IHttpResponseTransformer<T>,
responseType?: string): ng.IPromise<T> {
if (!method) {
throw new ArgumentNullError("method");
}
return this.innerHandler.post(
this.rootEndPoint + method,
data,
cancellationToken || this.timeout,
this.defaultRequestHeaders,
transformResponse,
responseType)
.then((x: any) => x.data);
}
public createCancellationTokenSource(): CancellationTokenSource {
return new CancellationTokenSource(this.$q.defer<void>());
};
protected validStatusCode(status: number): boolean {
return 200 <= status && status <= 299;
}
protected parseJSON(json: any): any {
return typeof json === "string"
? JSON.parse(json)
: json;
}
}
}
//#endregion
<# foreach(var enumType in enumTypes) { #>
export enum <#= enumType.Name #> {
<# foreach(var enumMember in Enum.GetNames(enumType).Select(x => new { Name = x, Value = ((Enum)Enum.Parse(enumType, x)).ToString("d") }).ToArray()) { #>
<#= enumMember.Name #> = <#= enumMember.Value #><#= Enum.GetNames(enumType).Last() == enumMember.Name ? "" : "," #>
<# } #>
}
<# } #>
<# foreach(var parameterType in parameterTypes) { #>
export interface I<#= parameterType.Name #> {
<# foreach(var p in parameterType.GetProperties().Where(x => x.CanRead).ToArray()) { #>
<#= ToLowerCamelCase(p.Name) #>: <#= BeautifyType(p.PropertyType) #>;
<# } #>
}
<# } #>
<# foreach(var complexType in complexTypes) { #>
export class <#= complexType.Name #> {
constructor(json?: any) {
<# foreach(var p in complexType.GetProperties().Where(x => x.CanRead).ToArray()) { #>
<# if(ShouldCreateInstance(p.PropertyType)) { #>
<# if(IsEnumerableType(p.PropertyType)) { #>
this.<#= ToLowerCamelCase(p.Name) #> = (<any[]>json.<#= p.Name #> || []).map((x: any) => x ? new <#= BeautifyType(p.PropertyType).TrimEnd('[', ']') #>(x) : null);
<# } else { #>
this.<#= ToLowerCamelCase(p.Name) #> = json.<#= allowUpperCamelJson ? p.Name : ToLowerCamelCase(p.Name) #> ? new <#= BeautifyType(p.PropertyType) #>(json.<#= allowUpperCamelJson ? p.Name : ToLowerCamelCase(p.Name) #>) : null;
<# } #>
<# } else { #>
this.<#= ToLowerCamelCase(p.Name) #> = json.<#= allowUpperCamelJson ? p.Name : ToLowerCamelCase(p.Name) #><#= IsEnumerableType(p.PropertyType) ? " || []" : "" #>;
<# } #>
<# } #>
}
<# foreach(var p in complexType.GetProperties().Where(x => x.CanRead).ToArray()) { #>
public <#= ToLowerCamelCase(p.Name) #>: <#= BeautifyType(p.PropertyType) #>;
<# } #>
}
<# } #>
export namespace Controllers {
<# foreach(var controller in controllers) { #>
export interface <#= controller.InterfaceName #> {
<# foreach(var action in controller.Actions) { #>
<#= ToLowerCamelCase(action.Name) #>(<#= action.ParameterString #>): ng.IPromise<<#= BeautifyType(action.ReturnType) #>>;
<# } #>
}
<# } #>
}
/**
* Provides webapi methods.
* Use the annotation of "<#= clientName #>".
*/
export class WebApiClient extends Core.WebApiClientBase {
constructor($q: ng.IQService, rootEndPoint: string, innerHandler: Core.WebApiClientHandler) {
super($q, rootEndPoint, innerHandler);
}
<# foreach(var controller in controllers) { #>
private _<#= ToLowerCamelCase(controller.Name) #>: Controllers.<#= controller.InterfaceName #>;
/**
* Provides methods of <#= controller.Name #>Controller.
*/
public get <#= ToLowerCamelCase(controller.Name) #>(): Controllers.<#= controller.InterfaceName #> {
if (!this._<#= ToLowerCamelCase(controller.Name) #>) {
this._<#= ToLowerCamelCase(controller.Name) #> = {
<# for(var i = 0; i < controller.Actions.Length; i++) { #>
<#= ToLowerCamelCase(controller.Actions[i].Name) #>: this.<#= ToLowerCamelCase(controller.Name) #><#= controller.Actions[i].Name #>.bind(this)<#= i == controller.Actions.Length - 1 ? "" : "," #>
<# } #>
};
}
return this._<#= ToLowerCamelCase(controller.Name) #>;
}
<# } #>
<# foreach(var controller in controllers) { #>
<# foreach(var action in controller.Actions) { #>
protected <#= ToLowerCamelCase(controller.Name) #><#= action.Name #>(<#= action.ParameterStringWithOptional #>): ng.IPromise<<#= BeautifyType(action.ReturnType) #>> {
<# if(action.IsComplexTypeParameter) { #>
let data = <#= ToLowerCamelCase(action.Parameters.First().Name) #>
<# } else if(action.Parameters.Any(x => !x.IsCancellationToken)) { #>
let data = {
<# foreach(var parameter in action.Parameters.Where(x => !x.IsCancellationToken)) { #>
"<#= ToLowerCamelCase(parameter.Name) #>": <#= parameter.IsBoolean ? "!!" : "" #><#= ToLowerCamelCase(parameter.Name) #><#= action.Parameters.Where(x => !x.IsCancellationToken).Last() == parameter ? "" : "," #>
<# } #>
};
<# } else { #>
let data = {};
<# } #>
<# if(action.ReturnType == typeof(void) ) { #>
return this.post<<#= BeautifyType(action.ReturnType) #>>("/<#= controller.Name #>/<#= action.Name #>", data, cancellationToken);
<# } else { #>
return this.post<<#= BeautifyType(action.ReturnType) #>>("/<#= controller.Name #>/<#= action.Name #>", data, cancellationToken,
(data: any, headersGetter: ng.IHttpHeadersGetter, status: number) => {
<# if(ShouldCreateInstance(action.ReturnType)) { #>
if (!this.validStatusCode(status)) {
return data;
}
<# if(IsEnumerableType(action.ReturnType)) { #>
return (<any[]>this.parseJSON(data) || []).map((x: any) => x ? new <#= BeautifyType(action.ReturnType).TrimEnd('[', ']') #>(x) : null);
<# } else { #>
let json = this.parseJSON(data);
return json ? new <#= BeautifyType(action.ReturnType) #>(json) : null;
<# } #>
<# } else { #>
return <#= action.IsReturnBinary ? "" : "this.parseJSON(" #>data<#= action.IsReturnBinary ? "" : ")" #>;
<# } #>
}<#= action.IsReturnBinary ? @", ""arraybuffer""" : "" #>);
<# } #>
}
<# } #>
<# } #>
}
}
/* tslint:enable */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment