Hi,
I need to add a field to the Service "isLoading" and set its value before sending the request to the server to be true and when the response is back to be false.
How can I do this with NSWAG (Angular 4 and Typescript)?
Thank you
Bilal
Can you post a sample?
Hi @RSuter ,
I just made it work :-)
Here is a sample:
````
@Injectable()
export class UsersServiceProxyExtensions extends UsersServiceProxy {
public isLoading = false;
constructor(private _http: Http, @Optional() @Inject(API_BASE_URL) _baseUrl?: string) {
super(_http, _baseUrl);
}
public getUsers(input: GetUsersInputDto): Observable<GetUsersOutputDto> {
const self = this;
self.isLoading = true;
return super.getUsers(input).do(() => self.isLoading = !self.isLoading);
}
}
````
Regards
Bilal H.
To avoid implementing an additional class, you can also mark the method getUsers as protected (ProtectedMethods setting) and extend the UsersServiceProxy with extension code (ExtensionCode and ExtensionClasses = ["UsersServiceProxy"])...
Hi @RSuter,
I am using the .nswag file to do the generations, so I must enable this setting ProtectedMethods in the configuration file?
Where would I place the extension code? Any sample?
Thanks
https://github.com/RSuter/NSwag/wiki/SwaggerToTypeScriptClientGenerator#extended-classes-and-extension-code

Sample (but without ExtendedClasses just extension code):
https://github.com/RSuter/NSwag/blob/master/src/NSwag.Sample.NetCoreAngular/nswag.json#L53
Thanks, @RSuter a lot.
@RSuter
Hi,
I am adding the following to the nswag config file:
"extendedClasses": ["Users"],
"protectedMethods": ["GetUsers"],
I am not seeing any code generated in the extensionCode.
Users ==> UsersController
GetUsers ==> name of the action on the server side
ProtectedMethods must be "UsersServiceProxy.getUsers"
ExtendedClasses must be "UsersServiceProxy"
And ExtensionCode must be (I think) something like:
```
import * as generated from "./apiClients";
class UsersServiceProxy extends generated.UsersServiceProxy {
public getUsers() {
return this.getUsersCore();
}
}
@RSuter Thanks, it works!
@RSuter
It seems I am facing more issues now.
In my second case, I need to change the existing function (the way is done by NSWAG) to completely something new.
Here is the code:
````
import { Http } from '@angular/http';
import * as generated from './apiClients';
import { GetUsersInputDto, GetUsersOutputDto, DataSourceResult } from '../src/app/shared/service-proxies/service-proxies';
import {
toDataSourceRequestString,
translateDataSourceResultGroups,
translateAggregateResults,
DataResult,
DataSourceRequestState
} from '@progress/kendo-data-query';
import { GridDataResult, DataStateChangeEvent } from '@progress/kendo-angular-grid';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
class UsersServiceProxy extends generated.UsersServiceProxy {
public isLoading = false;
getSecurityMatrix(state: DataSourceRequestState, filter: string, email: string): Observable<DataResult> {
setTimeout(() => {
this.isLoading = true;
});
const queryStr = `${toDataSourceRequestString(state)}`; // Serialize the state
const hasGroups = state.group && state.group.length;
const filterQs = filter ? `&filter=${filter}` : '';
const emailQs = email ? `&email=${email}` : '';
return this.http
.get(`${this.baseUrl}?${queryStr}${emailQs}${filterQs}`) // Send the state to the server
.do(() => this.isLoading = false)
.map(response => response.json())
.map(({data, total/*, aggregateResults*/}) => // Process the response
(<GridDataResult>{
data: hasGroups ? translateDataSourceResultGroups(data) : data,
total: total
})
);
}
}
````
Now when I run NSWAG, I get the following exception:
```
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at System.ThrowHelper.ThrowKeyNotFoundException()
at System.Collections.Generic.Dictionary2.get_Item(TKey key)
at NJsonSchema.CodeGeneration.ExtensionCode.GetExtensionClassBody(String className)
at NSwag.CodeGeneration.TypeScript.Models.TypeScriptClientTemplateModel.get_HasExtendedConstructor()
at NSwag.CodeGeneration.TypeScript.Templates.AngularClientTemplate.TransformText()
at NSwag.CodeGeneration.TypeScript.Templates.AngularClientTemplate.Render()
at NSwag.CodeGeneration.ClientGeneratorBase`3.GenerateFile(SwaggerDocument document, ClientGeneratorOutputType type)
at NSwag.Commands.SwaggerToTypeScriptClientCommand.<
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NSwag.Commands.SwaggerToTypeScriptClientCommand.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NSwag.Commands.SwaggerToTypeScriptClientCommand.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NSwag.Commands.NSwagDocumentBase.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NSwag.Commands.Document.ExecuteDocumentCommandBase.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NSwag.Commands.Document.ExecuteDocumentCommandBase.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NConsole.CommandLineProcessor.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NConsole.CommandLineProcessor.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NConsole.CommandLineProcessor.Process(String[] args, Object input)
at NSwag.Commands.NSwagCommandProcessor.Process(String[] args)child_process.js:524
throw err;
^
Error: Command failed: "...\node_modules\nswag\bin/binaries/full/nswag.exe" run
at checkExecSyncError (child_process.js:481:13)
at Object.execSync (child_process.js:521:13)
at Object.
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:389:7)
````
This is the JSON generated:
````
"/api/Users/GetSecurityMatrix": {
"get": {
"tags": [
"Users"
],
"operationId": "ApiUsersGetSecurityMatrixGet",
"consumes": [
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "request",
"in": "query",
"required": false
},
{
"name": "filter",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "email",
"in": "query",
"required": false,
"type": "string"
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/DataSourceResult"
}
}
}
}
},
````
I think the extension code does not contain all extended classes
@RSuter ,
Can you illustrate more on that? I sent you by email the json also just in case. Thanks
Can you post the content of ExtensionCode and the specified ExtendedClasses?
Actually, I am not able to generate the client-side code. That's why I sent you the json file, I dunno what happened!
I think the problem is that you specified an ExtendedTypes which is not present in ExtensionCode...
@RSuter
Here is the ExtensionCode:
````
import { Http } from '@angular/http';
import * as generated from './apiClients';
import { GetUsersInputDto, GetUsersOutputDto, DataSourceResult } from '../src/app/shared/service-proxies/service-proxies';
import {
toDataSourceRequestString,
translateDataSourceResultGroups,
translateAggregateResults,
DataResult,
DataSourceRequestState
} from '@progress/kendo-data-query';
import { GridDataResult, DataStateChangeEvent } from '@progress/kendo-angular-grid';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
class UsersServiceProxy extends generated.UsersServiceProxy {
public isLoading = false;
public getUsers(input: GetUsersInputDto): Observable<GetUsersOutputDto> {
setTimeout(() => {
this.isLoading = true;
}, 0);
return this.getUsersCore(input).do(() => this.isLoading = false);
}
public getSecurityMatrix(request: DataSourceRequestState, filter: string, email: string): Observable<DataResult> {
setTimeout(() => {
this.isLoading = true;
});
const queryStr = `${toDataSourceRequestString(request)}`; // Serialize the state
const hasGroups = request.group && request.group.length;
const filterQs = filter ? `&filter=${filter}` : '';
const emailQs = email ? `&email=${email}` : '';
return this.http
.get(`${this.baseUrl}?${queryStr}${emailQs}${filterQs}`) // Send the state to the server
.do(() => this.isLoading = false)
.map(response => response.json())
.map(({data, total/*, aggregateResults*/}) => // Process the response
(<GridDataResult>{
// If there are groups, convert them to a compatible format
data: hasGroups ? translateDataSourceResultGroups(data) : data,
total: total,
// Convert the aggregates if such exist
// aggregateResult: translateAggregateResults(aggregateResults)
})
);
}
}
````
And the original class generated is:
````
@Injectable()
export class UsersServiceProxy {
private http: Http;
private baseUrl: string;
protected jsonParseReviver: (key: string, value: any) => any = undefined;
constructor(@Inject(Http) http: Http, @Optional() @Inject(API_BASE_URL) baseUrl?: string) {
this.http = http;
this.baseUrl = baseUrl ? baseUrl : "";
}
public isLoading = false;
public getUsers(input: GetUsersInputDto): Observable<GetUsersOutputDto> {
setTimeout(() => {
this.isLoading = true;
}, 0);
return this.getUsersCore(input).do(() => this.isLoading = false);
}
public getSecurityMatrix(request: any, filter: string, email: string): Observable<DataSourceResult> {
setTimeout(() => {
this.isLoading = true;
});
return this.getSecurityMatrixCore(request, filter, email).do(() => this.isLoading = false);
}
/**
* @return Success
*/
protected getUsersCore(input: GetUsersInputDto): Observable<GetUsersOutputDto> {
let url_ = this.baseUrl + "/api/Users/GetUsers";
url_ = url_.replace(/[?&]$/, "");
const content_ = JSON.stringify(input);
let options_ = {
body: content_,
method: "post",
headers: new Headers({
"Content-Type": "application/json",
"Accept": "application/json"
})
};
return this.http.request(url_, options_).flatMap((response_) => {
return this.processGetUsers(response_);
}).catch((response_: any) => {
if (response_ instanceof Response) {
try {
return this.processGetUsers(response_);
} catch (e) {
return <Observable<GetUsersOutputDto>><any>Observable.throw(e);
}
} else
return <Observable<GetUsersOutputDto>><any>Observable.throw(response_);
});
}
protected processGetUsers(response: Response): Observable<GetUsersOutputDto> {
const status = response.status;
let _headers: any = response.headers ? response.headers.toJSON() : {};
if (status === 200) {
const _responseText = response.text();
let result200: any = null;
let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result200 = resultData200 ? GetUsersOutputDto.fromJS(resultData200) : new GetUsersOutputDto();
return Observable.of(result200);
} else if (status !== 200 && status !== 204) {
const _responseText = response.text();
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
}
return Observable.of<GetUsersOutputDto>(<any>null);
}
/**
* @return Success
*/
protected getSecurityMatrixCore(request: any, filter: string, email: string): Observable<DataSourceResult> {
let url_ = this.baseUrl + "/api/Users/GetSecurityMatrix?";
if (request !== undefined)
url_ += "request=" + encodeURIComponent("" + request) + "&";
if (filter !== undefined)
url_ += "filter=" + encodeURIComponent("" + filter) + "&";
if (email !== undefined)
url_ += "email=" + encodeURIComponent("" + email) + "&";
url_ = url_.replace(/[?&]$/, "");
let options_ = {
method: "post",
headers: new Headers({
"Content-Type": "application/json",
"Accept": "application/json"
})
};
return this.http.request(url_, options_).flatMap((response_) => {
return this.processGetSecurityMatrix(response_);
}).catch((response_: any) => {
if (response_ instanceof Response) {
try {
return this.processGetSecurityMatrix(response_);
} catch (e) {
return <Observable<DataSourceResult>><any>Observable.throw(e);
}
} else
return <Observable<DataSourceResult>><any>Observable.throw(response_);
});
}
protected processGetSecurityMatrix(response: Response): Observable<DataSourceResult> {
const status = response.status;
let _headers: any = response.headers ? response.headers.toJSON() : {};
if (status === 200) {
const _responseText = response.text();
let result200: any = null;
let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result200 = resultData200 ? DataSourceResult.fromJS(resultData200) : new DataSourceResult();
return Observable.of(result200);
} else if (status !== 200 && status !== 204) {
const _responseText = response.text();
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
}
return Observable.of<DataSourceResult>(<any>null);
}
}
````
@RSuter
Hello Rico, any idea what might be going on here? Thanks
What ExtendedClasses have to specified?
@RSuter
"extensionCode": "service.extensions.ts",
"extendedClasses": ["UsersServiceProxy"],
"protectedMethods": ["UsersServiceProxy.getUsers", "UsersServiceProxy.getSecurityMatrix"],
Can't see a problem from looking at it... you should probably clone the repo, start NSwagStudio and debug this problem (choose Runtime: Debug)
Do you detailed steps on how to do so? I'm not using studio btw I'm just
writing the configuration file myself.
Thanks
On 27 Oct 2017 1:14 am, "Rico Suter" notifications@github.com wrote:
Can't see a problem from looking at it... you should probably clone the
repo, start NSwagStudio and debug this problem (choose Runtime: Debug)
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/RSuter/NSwag/issues/1012#issuecomment-339816562, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ABHAnXe7Dyq3EL1VC9aK5rkr_ImSiuL5ks5swQQ-gaJpZM4QEZHR
.
Hi @RSuter
I downloaded NSWAG Studio and tried to debug. Things are a bit improving. Now I get this exception:
I already have defined the class UsersServiceProxy inside the service.extensions.ts file
Any idea?
Thanks
````
System.InvalidOperationException: The extension class 'UsersServiceProxy' is not defined.
Runtime: Default
at NJsonSchema.CodeGeneration.ExtensionCode.GetExtensionClassBody(String className)
at NSwag.CodeGeneration.TypeScript.Models.TypeScriptClientTemplateModel.get_HasExtendedConstructor()
at NSwag.CodeGeneration.TypeScript.Templates.AngularClientTemplate.TransformText()
at NSwag.CodeGeneration.TypeScript.Templates.AngularClientTemplate.Render()
at NSwag.CodeGeneration.ClientGeneratorBase`3.GenerateFile(SwaggerDocument document, ClientGeneratorOutputType type)
at NSwag.Commands.SwaggerToTypeScriptClientCommand.<
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NSwag.Commands.SwaggerToTypeScriptClientCommand.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NSwag.Commands.SwaggerToTypeScriptClientCommand.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NSwag.Commands.NSwagDocument.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NSwag.Commands.Document.ExecuteDocumentCommand.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NSwag.Commands.Document.ExecuteDocumentCommand.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NConsole.CommandLineProcessor.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NConsole.CommandLineProcessor.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NConsole.CommandLineProcessor.Process(String[] args, Object input)
at NSwag.Commands.NSwagCommandProcessor.Process(String[] args)
````
Most helpful comment
Sample (but without ExtendedClasses just extension code):
https://github.com/RSuter/NSwag/blob/master/src/NSwag.Sample.NetCoreAngular/nswag.json#L53