Method Inputs
This document outlines the method input signatures that language emitters will generate.
Basic
HTTP Get
@getop get(): User;
def get() -> User: ...
//protocol methodpublic virtual async Task<Response> GetUserAsync(RequestContext context){}public virtual Response GetUser(RequestContext context){}//convenience methodpublic virtual async Task<Response<User>> GetUser(CancellationToken cancellationToken = default)public virtual Response<User> GetUser(CancellationToken cancellationToken = default)
// from user experience perspective
// RLCexport interface GetUser200Response extends HttpResponse { status: "200"; body: User;}
export type DemoServiceContext = Client & { path: { /** Resource for '/analyze' has methods for the following verbs: post */ (path: "/users"): { get( options: RequestParameters, ): StreamableMethod<GetUser200Response | GetUserDefaultResponse>; }; };};
// Modular Api Layerexport async function get(): Promise<User>;
// Modular classical client layerexport class DemoServiceClient { get(options: GetUserOptionalParams): Promise<User>;}
public User get();
type ClientGetOptions struct {}
type ClientGetResponse struct {}
func (client *Client) Get(ctx context.Context, options *ClientGetOptions) (ClientGetResponse, error)
HTTP Post
@postop post(@body body: User): void;
For model inputs, Python automatically generates an overload that allows SDK users to input through a file stream.
@overloaddef post(body: User, **kwargs: Any) -> None: ...
@overloaddef post(body: JSON, **kwargs: Any) -> None: ...
@overloaddef post(body: IO[bytes], **kwargs: Any) -> None: ...
def post(body: [User, JSON, IO[bytes]], **kwargs: Any) -> None: ...
//protocol methodpublic virtual async Task<Response> PostAsync(RequestContent content, RequestContext context = null)public virtual Response Post(RequestContent content, RequestContext context = null)//convenience methodpublic virtual async Task<Response> PostAsync(User user, CancellationToken cancellationToken = default)public virtual Response Post(User user, CancellationToken cancellationToken = default)
// from user experience perspective
export type DemoServiceContext = Client & { path: { /** Resource for '/completions' has methods for the following verbs: post */ (path: "/users"): { post( options: { body: User; } & RequestParameters, ): StreamableMethod<PostUserDefaultResponse>; }; };};
// Modular Api Layerexport async function post(body: User, options: PostOptionalParams): Promise<void>;
// Modular classical client layerexport class DemoServiceClient { post(body: User, options: PostOptionalParams): Promise<void>;}
public void post(User user);
type ClientPostOptions struct {}
type ClientPostResponse struct {}
func (client *Client) Post(ctx context.Context, user User, options *ClientPostOptions) (ClientPostResponse, error)
Spread
Please exercise caution when using the spread feature.
- The model to be spread should have fewer than 6 settable properties. See simple methods.
- The model to be spread should remain stable across api-versions. Adding an optional property across api-versions could result in one additional method overload in SDK client.
- The model to be spread should not be used in JSON Merge Patch.
Alias
alias User = { firstName: string; lastName: string;};
@postop upload(...User): void;
For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.
def upload(first_name: str, last_name: str) -> None: ...
//protocol methodpublic virtual async Task<Response> UploadAsync(RequestContent content, RequestContext context = null)public virtual Response Upload(RequestContent content, RequestContext context = null)//convenience methodpublic virtual async Task<Response> UploadAsync(string firstName, string lastName, CancellationToken cancellationToken = default)public virtual Response Upload(string firstName, string lastName, CancellationToken cancellationToken = default)
// from user experience perspective
export type DemoServiceContext = Client & { path: { /** Resource for '/completions' has methods for the following verbs: post */ (path: "/users"): { post( options: { body: { firstName: string; lastName: string; }; } & RequestParameters, ): StreamableMethod<PostUserDefaultResponse>; }; };};
// Modular Api Layerexport async function upload( firstName: string, lastName: string, options: UploadOptionalParams,): Promise<void>;
// Modular classical client layerexport class DemoServiceClient { upload(firstName: string, lastName: string, options: UploadOptionalParams): Promise<void>;}
public void upload(String firstName, String lastName);
type ClientUploadOptions struct {}
type ClientUploadResponse struct {}
func (client *Client) Upload(ctx context.Context, firstName string, lastName string, options *ClientUploadOptions) (ClientUploadResponse, error)
Alias with @header/@query/@path properties
alias User = { @path id: string; firstName: string; lastName: string;};
op upload(...User): void;
For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.
def upload(self, id: str, first_name: str, last_name: str, *, content_type: str = "application/json") -> None: ...
//protocol methodpublic virtual async Task<Response> UploadAsync(string id, RequestContent content, RequestContext context = null)public virtual Response Upload(string id, RequestContent content, RequestContext context = null)//convenience methodpublic virtual async Task<Response> UploadAsync(string id, string firstName, string lastName, CancellationToken cancellationToken = default)public virtual Response Upload(string id, string firstName, string lastName, CancellationToken cancellationToken = default)
// from user experience perspective
export type DemoServiceContext = Client & { path: { /** Resource for '/completions' has methods for the following verbs: post */ ( path: "/users/{id}", id, ): { post( options: { body: { firstName: string; lastName: string; }; } & RequestParameters, ): StreamableMethod<PostUserDefaultResponse>; }; };};
// Modular Api Layerexport async function upload( id: string, firstName: string, lastName: string, options: UploadOptionalParams,): Promise<void>;
// Modular classical client layerexport class DemoServiceClient { upload( id: string, firstName: string, lastName: string, options: UploadOptionalParams, ): Promise<void>;}
public void upload(String id, String firstName, String lastName);
type ClientUploadOptions struct {}
type ClientUploadResponse struct {}
func (client *Client) Upload(ctx context.Context, id string, firstName string, lastName string, options *ClientUploadOptions) (ClientUploadResponse, error)
Named model
model User { firstName: string; lastName: string;}
op upload(...User): void;
For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.
def upload(self, first_name: str, last_name: str, *, content_type: str = "application/json") -> None: ...
public partial class User{ public User(string firstName, string lastName) { } public string FirstName { get; } public string LastName { get; }}//protocol methodpublic virtual async Task<Response> UploadAsync(RequestContent content, RequestContext context = null)public virtual Response Upload(RequestContent content, RequestContext context = null)//convenience methodpublic virtual async Task<Response> UploadAsync(User user, CancellationToken cancellationToken = default)public virtual Response Upload(string firstName, string lastName, CancellationToken cancellationToken = default)
// from user experience perspective
export type DemoServiceContext = Client & { path: { /** Resource for '/completions' has methods for the following verbs: post */ (path: "/users"): { post( options: { body: { firstName: string; lastName: string; }; } & RequestParameters, ): StreamableMethod<PostUserDefaultResponse>; }; };};
// Modular Api Layerexport async function upload( firstName: string, lastName: string, options: UploadOptionalParams,): Promise<void>;
// Modular classical client layerexport class DemoServiceClient { upload(firstName: string, lastName: string, options: UploadOptionalParams): Promise<void>;}
public void upload(String firstName, String lastName);
type ClientUploadOptions struct {}
type ClientUploadResponse struct {}
func (client *Client) Upload(ctx context.Context, firstName string, lastName string, options *ClientUploadOptions) (ClientUploadResponse, error)
Model with @body
property
model User { firstName: string; lastName: string;}
model UserRequest { @body user: User;}
op upload(...UserRequest): void;
For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.
def upload(self, body: [User, JSON, IO[bytes]], *, content_type: str = "application/json") -> None: ...
public partial class User{ public User(string firstName, string lastName){} public string FirstName { get; } public string LastName { get; }}//protocol methodpublic virtual async Task<Response> UploadAsync(RequestContent content, RequestContext context = null)public virtual Response Upload(RequestContent content, RequestContext context = null)//convenience methodpublic virtual async Task<Response> UploadAsync(User user, CancellationToken cancellationToken = default)public virtual Response Upload(User user, CancellationToken cancellationToken = default)
// from user experience perspective
export type DemoServiceContext = Client & { path: { /** Resource for '/completions' has methods for the following verbs: post */ (path: "/users"): { post( options: { body: User; } & RequestParameters, ): StreamableMethod<PostUserDefaultResponse>; }; };};
// Modular Api Layerexport async function upload(user: User, options: UploadOptionalParams): Promise<void>;
// Modular classical client layerexport class DemoServiceClient { upload(user: User, options: UploadOptionalParams): Promise<void>;}
// Model class@Immutablepublic final class User implements JsonSerializable<User> { public User(String firstName, String lastName); public String getFirstName(); public String getLastName();}
// Client APIpublic void upload(User user);
type User struct { firstName *string lastName *string}
type ClientUploadOptions struct {}
type ClientUploadResponse struct {}
func (client *Client) Upload(ctx context.Context, user User, options *ClientUploadOptions) (ClientUploadResponse, error)
Model with @header/@query/@path properties
model BlobProperties { @path name: string;
@header testHeader: string;}
@route("blob_properties/{name}")op getBlobProperties(...BlobProperties): void;
For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.
def get_blob_properties(self, name: str, *, test_header: string, content_type: str = "application/json") -> None: ...
//protocol methodpublic virtual async Task<Response> GetBlobPropertiesAsync(string name, string testHeader, RequestContext context = null)public virtual Response GetBlobProperties(string name, string testHeader, RequestContext context = null)
// from user experience perspective
export type DemoServiceContext = Client & { path: { /** Resource for '/completions' has methods for the following verbs: post */ (path: "/blob_properties/{name}", name): { post( options: { headers: { "test-header": string; } & RawHttpHeaders } & RequestParameters ): StreamableMethod<PostUserDefaultResponse>; }; };};
// Modular Optionsexport interface GetBlobPropertiesOptionalParams extends OperationOptions { requestOptions: { headers: { test-header: string } & RawHttpHeadersInput }}
// Modular api layerexport async function getBlobProperties(name: string, options: GetBlobPropertiesOptionalParams): Promise<void>;
// Modular classical client layerexport class DemoServiceClient { getBlobProperties(name: string, options: GetBlobPropertiesOptionalParams): Promise<void>}
public void getBlobProperties(String name, String testHeader);
type ClientGetBlobPropertiesOptions struct {}
type ClientGetBlobPropertiesResponse struct {}
func (client *Client) GetBlobProperties(ctx context.Context, name string, testHeader string, options *ClientGetBlobPropertiesOptions) (ClientGetBlobPropertiesResponse, error)
Model mixed with normal and @header/@query/@path properties
model Schema { @header contentType: "application/json"; schema: bytes;}
@postop register(...Schema): void;
For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.
class Schema: schema: bytes
def register(self, body: [Schema, JSON, IO[bytes]], *, content_type: str = "application/json") -> None: ...
public partial class Schema{ public Schema(BinaryData schemaProperty){} public BinaryData SchemaProperty { get; }}//protocol methodpublic virtual async Task<Response> RegisterAsync(RequestContent content, RequestContext context = null)public virtual Response Register(RequestContent content, RequestContext context = null)//convenience methodpublic virtual async Task<Response> RegisterAsync(Schema schema, CancellationToken cancellationToken = default)public virtual Response Register(Schema schema, CancellationToken cancellationToken = default)
// from user experience perspective
export type DemoServiceContext = Client & { path: { /** Resource for '/completions' has methods for the following verbs: post */ (path: "/schemaRegister"): { post( options: { headers: { "content-type": "application/json"; } & RawHttpHeaders; body: { schema: string; }; } & RequestParameters, ): StreamableMethod<PostUserDefaultResponse>; }; };};
// Modular modelexport interface Schema { schema: string;}
// Modular api layerexport async function register( body: Schema, options: GetBlobPropertiesOptionalParams,): Promise<void>;
// Modular classical client layerexport class DemoServiceClient { getBlobProperties(body: Schema, options: GetBlobPropertiesOptionalParams): Promise<void>;}
// Model class@Immutablepublic final class Schema implements JsonSerializable<Schema> { public Schema(byte[] schema); public byte[] getSchema();}
// Client APIpublic void register(Schema schema);
type ClientRegisterOptions struct {}
type ClientRegisterResponse struct {}
func (client *Client) Register(ctx context.Context, schema []byte, options *ClientRegisterOptions) (ClientRegisterResponse, error)
Using Azure.Core.ResourceOperations template
Resource create and update operations are not impacted by spread since they all have explicit defined body parameter. Only resource action operations are impacted by spread.
If the action parameter is a model, then the model will be spread.
@resource("widgets")model Widget { @key("widgetName") name: string;}
model RepairInfo { problem: string; contact: string;}
model RepairResult { reason: string; info: string;}
alias Operations = Azure.Core.ResourceOperations<{}>;
op scheduleRepairs is Operations.ResourceAction<Widget, RepairInfo, RepairResult>;
For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.
class RepairInfo: problem: str contact: str
class RepairResult: reason: str info: str
def scheduleRepairs(self, widget_name: str, problem: str, contact: str, *, content_type: str = "application/json") -> RepairResult: ...
// from user experience perspective
export interface RepairInfo { problem: string; contact: string;}
export type WidgetServiceContext = Client & { path: { ( path: "/widgets/{widgetName}:scheduleRepairs", widgetName: string, ): { post( options: { body: RepairInfo; } & RequestParameters, ): StreamableMethod<PostUserDefaultResponse>; }; };};
// Modular api layerexport async function scheduleRepairs( context: Client, widgetName: string, problem: string, contact: string, options: ScheduleRepairsOptionalParams = { requestOptions: {} },): Promise<RepairResult>;
// Modular classical client layerexport class WidgetServiceClient { scheduleRepairs( widgetName: string, problem: string, contact: string, options: ScheduleRepairsOptionalParams = { requestOptions: {} }, ): Promise<RepairResult>;}
public RepairResult scheduleRepairs(String widgetName, String problem, String contact);
type ClientScheduleRepairsOptions struct {}
type RepairResult struct { reason *string info *string}
type ClientScheduleRepairsResponse struct { RepairResult}
func (client *Client) ScheduleRepairs(ctx context.Context, widgetName string, problem string, contact string, options *ClientScheduleRepairsOptions) (ClientScheduleRepairsResponse, error)
If you want to keep the model, you have two options to prevent spreading:
@override
- If you don’t want to do client customizations, you could use a wrapper to explicitly set the body to prevent spread.
1. @override
The @override
decorator allows you to replace the default client method generated by TCGC based on your service definition.
If your service definition spreads a model into the method signature, but you prefer that the generated client SDKs maintain the model intact, the @override
decorator provides a solution.
Additionally, you can specify a language scope
to limit the changes to a specific language emitter.
namespace Widget.Client;
op scheduleRepairs( body: RepairInfo, `api-version`: Azure.Core.Foundations.ApiVersionParameter,): RepairResult;
@@override(Widget.Service.scheduleRepairs, Widget.Client.scheduleRepairs);
2. wrapper
If you prefer not to implement customizations in client.tsp
, you can add @bodyRoot
to the input in main.tsp
prior to passing the model to the template.
namespace Widget.Service;
@resource("widgets")model Widget { @key("widgetName") name: string;}
model RepairInfo { problem: string; contact: string;}
model RepairResult { reason: string; info: string;}
alias Operations = Azure.Core.ResourceOperations<{}>;
alias BodyParameter< T, TName extends valueof string = "body", TDoc extends valueof string = "Body parameter."> = { @doc(TDoc) @friendlyName(TName) @bodyRoot body: T;};
op scheduleRepairs is Operations.ResourceAction<Widget, BodyParameter<RepairInfo>, RepairResult>;
For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.
class RepairInfo: problem: str contact: str
class RepairResult: reason: str info: str
def scheduleRepairs(self, body: [Schema, JSON, IO[bytes]], *, content_type: str = "application/json") -> RepairResult: ...
// from user experience perspective
export interface RepairInfo { problem: string; contact: string;}
export type WidgetServiceContext = Client & { path: { ( path: "/widgets/{widgetName}:scheduleRepairs", widgetName: string, ): { post( options: { body: RepairInfo; } & RequestParameters, ): StreamableMethod<PostUserDefaultResponse>; }; };};
// Modular api layerexport async function scheduleRepairs( context: Client, widgetName: string, body: RepairInfo, options: ScheduleRepairsOptionalParams = { requestOptions: {} },): Promise<RepairResult>;
// Modular classical client layerexport class WidgetServiceClient { scheduleRepairs( widgetName: string, body: RepairInfo, options: ScheduleRepairsOptionalParams = { requestOptions: {} }, ): Promise<RepairResult>;}
// Model class@Immutablepublic final class RepairInfo implements JsonSerializable<RepairInfo> { public RepairInfo(String problem, String contact); public String getProblem(); public String getContact();}
@Immutablepublic final class RepairResult implements JsonSerializable<RepairResult> { public String getReason(); public String getInfo();}
// Client APIpublic RepairResult scheduleRepairs(String widgetName, RepairInfo body);
type RepairInfo struct { problem *string contact *string}
type ClientScheduleRepairsOptions struct {}
type RepairResult struct { reason *string info *string}
type ClientScheduleRepairsResponse struct { RepairResult}
func (client *Client) ScheduleRepairs(ctx context.Context, widgetName string, body RepairInfo, options *ClientScheduleRepairsOptions) (ClientScheduleRepairsResponse, error)