<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Basic Requests</title><link>https://community.telligent.com/community/11/w/developer-training/65137/basic-requests</link><description /><dc:language>en-US</dc:language><generator>14.0.0.586 14</generator><item><title>Basic Requests</title><link>https://community.telligent.com/community/11/w/developer-training/65137/basic-requests</link><pubDate>Tue, 04 Aug 2020 18:54:02 GMT</pubDate><guid isPermaLink="false">8f68fa04-8bd9-4fba-96e0-23f93df30279</guid><dc:creator>Former Member</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65137/basic-requests#comments</comments><description>Current Revision posted to Developer Training by Former Member on 08/04/2020 18:54:02&lt;br /&gt;
&lt;p&gt;Making requests is dependent on understanding [[Hosts]]. &amp;nbsp;The functionality described here is common for all types of hosts but is inaccessible without instantiating or retrieving a host depending on the type of host in use. &amp;nbsp;It is recommended that you review the material on [[Hosts]], [[Client Credentials REST Host]] and [[Default REST Host]] before continuing with this topic.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;For the purposes of the examples in this topic we will be using the [[Client Credentials REST Host]]. &amp;nbsp;However its important to note that the process of making requests to REST is identical for any host once you have obtained an instance of the host.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2&gt;&lt;a id="Types_Of_Requests" name="Types_Of_Requests"&gt;&lt;/a&gt;Types Of Requests&lt;/h2&gt;
&lt;p&gt;The SDK allows for the same types of requests that the REST API supports. &amp;nbsp;These include GET, POST, PUT, DELETE as well as issuing Batch and Widget rendering requests. &amp;nbsp; You can access any REST Url your community currently supports. &amp;nbsp;If you try to make a request to a URL that your&amp;nbsp;community doesn&amp;#39;t support, for instance one only available in a newer version, it will fail. &amp;nbsp; The important reason for mentioning this is the SDK itself doesn&amp;#39;t understand what an endpoint is or does, it simply sees it as a REST Url that will respond with the appropriate payload.&lt;/p&gt;
&lt;h2&gt;&lt;a id="Types_Of_Responses" name="Types_Of_Responses"&gt;&lt;/a&gt;Types Of Responses&lt;/h2&gt;
&lt;p&gt;This is where the SDK earns its stripes. &amp;nbsp;When it comes to the community REST API, there are only 4 types of responses. &amp;nbsp;The 2 most common are XML or JSON. &amp;nbsp;Additionally some endpoints can return you raw binary data or even html data. &amp;nbsp;The SDK &amp;nbsp;can handle all of these and in some cases can give you a helping hand by parsing the response into a more useable &amp;nbsp;format. &amp;nbsp;These are the response types that are available in the SDK and when or how they can be used:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;String&lt;/strong&gt; - &amp;nbsp;This works for either a JSON or XML request. &amp;nbsp;In this case the JSON or XML payload is returned as a string. &amp;nbsp;This is also used if you are using an html based endpoint like the widget rendering endpoint.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stream&lt;/strong&gt; - This basically is returning you the response stream. &amp;nbsp;It works for all types of&amp;nbsp;calls. &amp;nbsp;You especially need this if your payload is raw binary data. &amp;nbsp;Otherwise you can read the stream into any appropriate form.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://msdn.microsoft.com/en-us/library/system.xml.linq.xelement(v=vs.110).aspx" rel="noopener noreferrer" target="_blank"&gt;XElement&lt;/a&gt;&lt;/strong&gt; - &amp;nbsp;This is only available when the REST API is responding with XML. &amp;nbsp;In this case the XML is read into an easy to use .NET XElement object.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://msdn.microsoft.com/en-us/library/dd264736.aspx" rel="noopener noreferrer" target="_blank"&gt;dynamic&lt;/a&gt;&lt;/strong&gt; - This can only be used with JSON response types because it&amp;#39;s the JSON that gets parsed into a dynamic object. &amp;nbsp;A dynamic object essentially allows you to work with the response like its was a strongly typed object without the actual need to create one.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;For each request type, you will find a method for each response type, with the exception of widget rendering which is essentially a GET request.&lt;/p&gt;
&lt;h2&gt;&lt;a id="Getting_Started" name="Getting_Started"&gt;&lt;/a&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;As has been mentioned it&amp;#39;s a host that gives you access to make REST calls. For the purposes of example this topic uses the [[Client Credentials REST Host]] but it is important to re-iterate that the calls illustrated in this topic are identical regardless of host, the only variance is how the host&amp;nbsp;is retrieved. &amp;nbsp; If you would like to try any of these examples you can create a new console application in Visual Studio then install the SDK as described [[REST SDK|here]].&lt;/p&gt;
&lt;h3&gt;&lt;a id="Loading_up_a_Host" name="Loading_up_a_Host"&gt;&lt;/a&gt;Loading up a Host&lt;/h3&gt;
&lt;p&gt;In our examples we have a simple method to load our host to avoid repetitive code. &amp;nbsp;You can do this inline as well if you choose. &amp;nbsp;You will also need to ensure you have setup an Oauth client that is private with a Client Credentials grant type. The urls can be whatever you want, they are not relevant using client credentials. &amp;nbsp;If you are unsure&amp;nbsp;how to do this refer to the OAuth section of the REST API&amp;#39;s [[Authentication]] topic.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;private static ClientCredentialsRestHost GetHost()
{
    return new ClientCredentialsRestHost(&amp;quot;admin&amp;quot;
        ,&amp;quot;http://yoursiteurl.com&amp;quot;
        , &amp;quot;[Your Client Id]&amp;quot;
        , &amp;quot;[Your Client Secret]&amp;quot;);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If you were using the [[Default REST Host]] you can use the same pattern with a small adjustment, assuming you have set it up correctly. &amp;nbsp; After this all the REST requests work exactly the same.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;private static Host GetHost()
{
     return Host.Get(&amp;quot;default&amp;quot;);
}&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Building_a_Request" name="Building_a_Request"&gt;&lt;/a&gt;Building a Request&amp;nbsp;&lt;/h2&gt;
&lt;p&gt;The way you make the types of requests with the types of responses we have discussed is through invoking particular methods on the host. &amp;nbsp;The naming pattern is constant for all of them so for each request type, there is an option for a different response type. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;Given this list of request types, essentially here is the available methods:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Host.GetTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;](...)&lt;/li&gt;
&lt;li&gt;Host.PostTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;](...)&lt;/li&gt;
&lt;li&gt;Host.PutTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;](...)&lt;/li&gt;
&lt;li&gt;Host.DeleteTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;](...)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally each of those has an async counterpart which we will cover more in depth later:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Host.GetTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;]Async(...)&lt;/li&gt;
&lt;li&gt;Host.PostTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;]Async(...)&lt;/li&gt;
&lt;li&gt;Host.PutTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;]Async(...)&lt;/li&gt;
&lt;li&gt;Host.DeleteTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;]Async(...)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a id="Anatomy_of_a_Request" name="Anatomy_of_a_Request"&gt;&lt;/a&gt;Anatomy of a Request&lt;/h3&gt;
&lt;p&gt;Every request requires a minimum of 2 pieces of information with the exception of the batch request which will be covered separately. &amp;nbsp; These are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;REST Version&lt;/strong&gt; - &amp;nbsp;This is the endpoint version. &amp;nbsp;If you were making a request manually it is part of the url (/api.ashx/v&lt;strong&gt;2&lt;/strong&gt;/...). &amp;nbsp;In the SDK the number from this required as the first argument.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Url&lt;/strong&gt; - This is the actual endpoint you are trying to contact WITHOUT /&lt;em&gt;api.ashx/v2/&lt;/em&gt;. &amp;nbsp; The&amp;nbsp;SDK will build this part of the url automatically using the version in the first argument.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Given this if we wanted to produce a GET request that required no parameters it would look like this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var host = GetHost();
var response = host.GetToDynamic(2, &amp;quot;info.json&amp;quot;);&lt;/pre&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Impersonation" name="Impersonation"&gt;&lt;/a&gt;Impersonation&lt;/h3&gt;
&lt;p&gt;Each request method gives you the ability to opt-in or out of impersonation. This however only works if the host you are using supports impersonation. &amp;nbsp;While it&amp;#39;s recommended that a host supports impersonation, it may not. &amp;nbsp;You should refer to your host&amp;#39;s documentation on how it handles impersonation of another user if at all. &amp;nbsp;If you know you do not wish to impersonate, you should pass in false for the enableImpersonation parameter. &amp;nbsp;The enableImpersonation argument is optional and when not supplied defaults to true.&lt;/p&gt;
&lt;p&gt;Consult the topic on the [[Client Credentials REST Host]] and [[Default REST Host]] for how this parameter is used and how they support impersonation.&lt;/p&gt;
&lt;p&gt;The following calls both will tell the host to use impersonation if its supported:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var host = GetHost();
var response = host.GetToDynamic(2, &amp;quot;info.json&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;OR&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var host = GetHost();
var response = host.GetToDynamic(2, &amp;quot;info.json&amp;quot;,true); //addition of &amp;quot;enableImpersonation&amp;quot; parameter&lt;/pre&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Options_Objects" name="Options_Objects"&gt;&lt;/a&gt;Options Objects&lt;/h3&gt;
&lt;p&gt;Options objects are classes passed in to each type of request that can have several optional arguments. This is also where additional optional arguments would be added in the future. &amp;nbsp;Options themselves are also&amp;nbsp;optional.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Querystring_Parameters" name="Querystring_Parameters"&gt;&lt;/a&gt;Querystring Parameters&lt;/h4&gt;
&lt;p&gt;Querystring parameters are parameters appended to the REST Url after a &amp;#39;?&amp;#39; symbol. &amp;nbsp;They are the most common on GET requests but are supported on all the request types. &amp;nbsp;You do not need to actually add them to the url yourself, instead if you evaluate the options object on the method you are calling you should find a property to add query string parameters.&lt;/p&gt;
&lt;p&gt;The following example illustrates a GET call using querystring parameters. &amp;nbsp;The pattern is the same for POST,PUT and DELETE requests as well.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var host = GetHost();

var querystring = new NameValueCollection();
querystring.Add(&amp;quot;pageSize&amp;quot;,&amp;quot;20&amp;quot;);
querystring.Add(&amp;quot;pageIndex&amp;quot;,&amp;quot;1&amp;quot;);

var response = host.GetToDynamic(2, &amp;quot;users.json&amp;quot;,true,new RestGetOptions()
{
    QueryStringParameters = querystring
});&lt;/pre&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="Path_Parameters" name="Path_Parameters"&gt;&lt;/a&gt;Path Parameters&lt;/h4&gt;
&lt;p&gt;Like querystring parameters path parameters are used to add dynamic data to a request however unlike querystring parameters these aren&amp;#39;t added to anything, rather they are substitution values, ususally meant to replace a value in the url.&lt;/p&gt;
&lt;p&gt;The substitution value is a key name surrounded by {}. &amp;nbsp;For example the key userid is a path parameter in the following url:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;users/{userid}.json&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;A path parameter can be at any position in the url string. &amp;nbsp; To define a value for a parameter you pass it in to the PathParameters of the options object. &amp;nbsp;PathParameters are supported on all GET,POST,PUT and DELETE requests. &amp;nbsp;You can define your own path parameter as well, as long as it is provided a value in the PathParameters collection.&lt;/p&gt;
&lt;p&gt;This example uses PathParameters in a simple GET.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var host = GetHost();
 
var pathParameters = new NameValueCollection();
pathParameters.Add(&amp;quot;userid&amp;quot;, &amp;quot;2100&amp;quot;);

var response = host.GetToDynamic(2, &amp;quot;users/{userid}.json&amp;quot;, true, new RestGetOptions()
{
   PathParameters = pathParameters
});&lt;/pre&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="Post_Parameters" name="Post_Parameters"&gt;&lt;/a&gt;Post Parameters&lt;/h4&gt;
&lt;p&gt;Unlike the other parameter types, PostParameters&amp;nbsp;are added to the request body rather than be part of the url. &amp;nbsp;These types of parameters are only supported for POST and PUT requests. &amp;nbsp; The following user creation method passes PostParameters:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var host = GetHost();

var postParameters = new NameValueCollection();
postParameters.Add(&amp;quot;Username&amp;quot;,&amp;quot;somerandomusername&amp;quot;);
postParameters.Add(&amp;quot;PrivateEmail&amp;quot;, &amp;quot;somerandomusername@localhost.com&amp;quot;);
postParameters.Add(&amp;quot;Password&amp;quot;,&amp;quot;SuperComplexPassword&amp;quot;);

var response = host.PostToDynamic(2, &amp;quot;users.json&amp;quot;, true, new RestPostOptions()
{
    PostParameters = postParameters
});&lt;/pre&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="Custom_Headers" name="Custom_Headers"&gt;&lt;/a&gt;Custom Headers&lt;/h4&gt;
&lt;p&gt;If for some reason you require custom headers from your application you can specify them on the options object. &amp;nbsp;This will also overwrite existing headers. &amp;nbsp;This should be supported on all request options objects.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var customHeaders = new NameValueCollection()
{
    {&amp;quot;X-App-Name&amp;quot;,&amp;quot;MyCustomApp&amp;quot;}
};

dynamic response = host.GetToDynamic(2, &amp;quot;info.json&amp;quot;, true, new RestGetOptions()
{
  AdditionalHeaders = customHeaders
});&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Handling_a_Response" name="Handling_a_Response"&gt;&lt;/a&gt;Handling a Response&lt;/h2&gt;
&lt;p&gt;Most of the response types are fairly straight forward and dealing with them is not really specific to using the SDK. &amp;nbsp;Here are the response types and how your code can potentially handle them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://msdn.microsoft.com/en-us/library/system.xml.linq.xelement(v=vs.110).aspx"&gt;XElement&lt;/a&gt; - &amp;nbsp;This gives you a .NET XElement object representing XML. &amp;nbsp;Using this element you can read the data using&lt;a href="https://msdn.microsoft.com/en-us/library/bb387098.aspx" rel="noopener noreferrer" target="_blank"&gt; LINQ to Xml &lt;/a&gt;queries.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stream&lt;/strong&gt; - There are different paths for streams depending on the payload. &amp;nbsp;For XML or JSON the stream can be read into memory and then used to deserialize the data into classes you have created in your application. &amp;nbsp;If the payload is a file you can read the stream into the appropriate file and save it to disk. &amp;nbsp;Generally you would not use stream to convert to a string because that option is already available.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;String&lt;/strong&gt; - This is most appropriate for Html or JSON return types. &amp;nbsp; You can use the string to output html directly or it can be used for JSON serialization or manipulation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last probably most powerful response is &lt;a href="https://msdn.microsoft.com/en-us/library/dd264741.aspx"&gt;dynamic&lt;/a&gt;&amp;nbsp;and while it is also not an SDK specific response type, its worth spending a bit more time on since&amp;nbsp;its relatively new. &amp;nbsp;The downside with these is that unlike strongly typed classes, there is no Intellisense help when writing code.&lt;/p&gt;
&lt;p&gt;You interact wth dynamics just like a class, by accessing its properties. &amp;nbsp;The difference however is that the properties &amp;nbsp;aren&amp;#39;t actually defined, they are dynamically bound at runtime.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A simple&amp;nbsp;example would be if you had a plain old object called &amp;quot;Foo&amp;quot; and you in your code you called the property &amp;quot;Name&amp;quot;. &amp;nbsp;If your Foo object does not&amp;nbsp;have a property called &amp;quot;Name&amp;quot;, your code will not compile. &amp;nbsp;This is because the compiler checks for these types of errors when compiling. &amp;nbsp;If Foo is type dynamic and you called Foo.Name the code would compile without error. &amp;nbsp;This is because this reference is ignored by the compiler for dynamics until runtime. &amp;nbsp; Using this concept we do not have to write a class for every possible response from the REST API. &amp;nbsp;We simply take the response and convert it to a type of dynamic. &amp;nbsp;This means you can code against the properties &amp;nbsp;even though the code does not yet know if a property exists yet. &amp;nbsp;Only after its evaluated at runtime if the property does not exist will it throw an error.&lt;/p&gt;
&lt;p&gt;We base the dynamic binding on the hierarchal structure of the JSON response so you can only use dynamic responses with JSON requests. &amp;nbsp;Review this JSON response(this response has been shortened for example purposes):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="json"&gt;{
  &amp;quot;InfoResult&amp;quot;: {
    &amp;quot;SiteName&amp;quot;: &amp;quot;sitename&amp;quot;,
    &amp;quot;SiteDescription&amp;quot;: &amp;quot;sitedescription&amp;quot;,
  },
  &amp;quot;AccessingUser&amp;quot;: {
    &amp;quot;ContentId&amp;quot;: &amp;quot;49fec544-6df7-4a82-872b-f8be586d5e9e&amp;quot;,
    &amp;quot;ContentTypeId&amp;quot;: &amp;quot;9f5a6721-639d-4e1d-ab6a-ce63b7750f46&amp;quot;,
    &amp;quot;DisplayName&amp;quot;: &amp;quot;displayname&amp;quot;,
    &amp;quot;Username&amp;quot;: &amp;quot;username&amp;quot;,
    &amp;quot;Id&amp;quot;: 6
  },
  &amp;quot;Errors&amp;quot;: [
    &amp;quot;string&amp;quot;,
    &amp;quot;string&amp;quot;
  ]
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In this example, InfoResult would be &amp;nbsp;a property of the dynamic object and Sitename would be a property of InfoResult. &amp;nbsp; Similarly AccessingUser is a property on the dynamic object and Username is a property of Accessing User.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;pre class="ui-code" data-mode="csharp"&gt;var host = GetHost();
var response = host.GetToDynamic(2, &amp;quot;info.json&amp;quot;);

Console.WriteLine(&amp;quot;Site Name:&amp;quot; + response.InfoResult.SiteName);
Console.WriteLine(&amp;quot;Accessing Username:&amp;quot; + response.AccessingUser.Username);&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Uploading_a_File" name="Uploading_a_File"&gt;&lt;/a&gt;Uploading a File&lt;/h2&gt;
&lt;p&gt;The SDK also supports uploading files to use as attachments to other pieces of contents. &amp;nbsp;The advantage of the SDK upload is it is similar to how you upload files in the UI. &amp;nbsp;If the file is under 15mb the whole file is sent, otherwise it is broken up into 15mb chunks and transmitted individually. &amp;nbsp;This bypasses request limits and helps avoid timeouts by spreading the file out over multiple requests. &amp;nbsp; Unlike other requests this will give you a strongly typed UploadedFileInfo argument back&amp;nbsp;in lieu of the other types of responses already discussed.&lt;/p&gt;
&lt;p&gt;Here is an example of a file upload in its most basic form&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using (var fileStream = new FileStream(&amp;quot;c:\\test.png&amp;quot;, FileMode.Open, FileAccess.Read))
{
   fileStream.Position = 0;
   Guid uploadContextId = Guid.NewGuid();
   UploadedFile file = new UploadedFile(uploadContextId, &amp;quot;test.png&amp;quot;, &amp;quot;image/png&amp;quot;, fileStream);

   UploadedFileInfo response = host.UploadFile(file);
   if (!response.IsError)
      Console.WriteLine(response.UploadContext);
   else
      Console.WriteLine(response.Message);
 }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;You can also track the progress of each chunk using the UploadProgess action on the delegate that will give you FileUploadProgress object to interact with. &amp;nbsp;Below we will print the percent complete.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using (var fileStream = new FileStream(&amp;quot;c:\\test.png&amp;quot;, FileMode.Open, FileAccess.Read))
{
   fileStream.Position = 0;
   Guid uploadContextId = Guid.NewGuid();
   UploadedFile file = new UploadedFile(uploadContextId, &amp;quot;test.png&amp;quot;, &amp;quot;image/png&amp;quot;, fileStream);

   UploadedFileInfo response = host.UploadFile(file,new RestFileOptions()
   {
       UploadProgress = (p) =&amp;gt;
          {
             Console.WriteLine(&amp;quot;Percent Complete:&amp;quot; + p.PercentComplete);
          }
    });
    
    if (!response.IsError)
         Console.WriteLine(response.UploadContext);
   else
         Console.WriteLine(response.Message);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;You can use that file to create an attachment to something like a forum thread using the context Id you specified:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using (var fileStream = new FileStream(&amp;quot;c:\\test.png&amp;quot;, FileMode.Open, FileAccess.Read))
{
    fileStream.Position = 0;
    Guid uploadContextId = Guid.NewGuid();
    UploadedFile file = new UploadedFile(uploadContextId, &amp;quot;test.png&amp;quot;, &amp;quot;image/png&amp;quot;, fileStream);

    UploadedFileInfo fileInfo = host.UploadFile(file,new RestFileOptions()
    {
        UploadProgress = (p) =&amp;gt;
        {
            Console.WriteLine(&amp;quot;Percent Complete:&amp;quot; + p.PercentComplete);
        }
    });
    
    f (!fileInfo.IsError)
    {
        var pathParameters = new NameValueCollection();
        pathParameters.Add(&amp;quot;forumid&amp;quot;,&amp;quot;2958&amp;quot;);

        var postParameters = new NameValueCollection();
       postParameters.Add(&amp;quot;Subject&amp;quot;,&amp;quot;This is a cool Forum&amp;quot;);
       postParameters.Add(&amp;quot;Body&amp;quot;,&amp;quot;I think I will post a thread in it&amp;quot;);
                        
        //Now add the file
        postParameters.Add(&amp;quot;FileName&amp;quot;, &amp;quot;test.png&amp;quot;);
       postParameters.Add(&amp;quot;ContentType&amp;quot;, &amp;quot;image/png&amp;quot;);
       postParameters.Add(&amp;quot;FileUploadContext&amp;quot;,fileInfo.UploadContext.ToString());//Use the upload context Id from our file upload


        dynamic threadResponse = host.PostToDynamic(2, &amp;quot;forums/{forumid}/threads.json&amp;quot;, true,
            new RestPostOptions()
            {
                PathParameters = pathParameters,
                PostParameters = postParameters
           });
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Batching" name="Batching"&gt;&lt;/a&gt;Batching&lt;/h2&gt;
&lt;p&gt;Batch requests are making several REST requests in a single call. &amp;nbsp;This reduces overhead because only the batch request is processed over HTTP, the containing requests are executed in process on the server. &amp;nbsp;The SDK makes batch requests easier as well since you don&amp;#39;t have to know the request format like you do making a batch request against REST&amp;nbsp;directly.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A batch request is a collection of batch request objects translated into individual requests before being sent to community.. &amp;nbsp; Batch request objects contain similar information to a single request method with a couple of exceptions. &amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The default APIVersion will always be &lt;strong&gt;2&lt;/strong&gt; though there is an &lt;strong&gt;APIVersion&lt;/strong&gt; property to override this value.&lt;/li&gt;
&lt;li&gt;Each request must have a sequence specified in the constructor, the sequence is a zero based so your first sequence value should be 0.**&lt;/li&gt;
&lt;li&gt;You must specify that a request is GET,POST etc in the &lt;strong&gt;RestMethod&lt;/strong&gt; property since a batch request itself is a POST.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;QueryString&lt;/strong&gt; and &lt;strong&gt;PostParameters&lt;/strong&gt; that you are used to in previous requests are collapsed into a single collection called RequestParameters and are used querystring or body parameters depending on the RestMethod. &amp;nbsp;PathParameters are separate and work the same.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;**Sequence is always required but only honored when a batch request is set to be sequential. &amp;nbsp;Otherwise the requests are processed in parallel on the server.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The following example executes a GET and POST request in a single request in parallel:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var batchRequestList = new List&amp;lt;BatchRequest&amp;gt;();
var userRequest = new BatchRequest(&amp;quot;users/{username}.json&amp;quot;, 0);
userRequest.RestMethod = RestMethod.GET;
serRequest.PathParameters = new NameValueCollection()
{
    {&amp;quot;username&amp;quot;,&amp;quot;pmason&amp;quot;}
};
batchRequestList.Add(userRequest);

var threadRequest = new BatchRequest(&amp;quot;forums/{forumid}/threads.json&amp;quot;, 1);
threadRequest.RestMethod = RestMethod.POST;
threadRequest.PathParameters = new NameValueCollection()
{
    {&amp;quot;forumid&amp;quot;,&amp;quot;2958&amp;quot;}
};

threadRequest.RequestParameters = new NameValueCollection()
{
    {&amp;quot;Subject&amp;quot;,&amp;quot;This is a great thread&amp;quot;},
    {&amp;quot;Body&amp;quot;,&amp;quot;I love this forum so much!&amp;quot;}
};
batchRequestList.Add(threadRequest);

dynamic response = host.BatchRequestToDynamic(2, batchRequestList, true);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;You can force &amp;nbsp;this to run sequentially, meaning each request will be run in order of its sequence value, by adding the options argument and setting the RunSequentially flag:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;dynamic response = host.BatchRequestToDynamic(2, batchRequestList, true,new BatchRequestOptions()
{
   RunSequentially = true
});&lt;/pre&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Batch responses are similar to the request, where you will get back a collection of the responses. &amp;nbsp; Each response has metadata about the response including the response code and then a BatchResponse property which is the response data returned from the request endpoint. &amp;nbsp;This data is identical to the format of the endpoint had it been done in a single request.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="json"&gt;{
    &amp;quot;BatchResponses&amp;quot;:[
        {
            &amp;quot;Url&amp;quot;: &amp;quot;api.ashx/v2/users/pmason.json&amp;quot;,
            &amp;quot;StatusCode&amp;quot;: 200,
            &amp;quot;Sequence&amp;quot;: 0,
            &amp;quot;BatchResponse&amp;quot;: {
                &amp;quot;User&amp;quot;: {
                    //This looks like the user SHOW response
                }
            }
        },
        {
            &amp;quot;Url&amp;quot;:&amp;quot;api.ashx/v2/forums/2958/threads.json&amp;quot;, 
            &amp;quot;StatusCode&amp;quot;:200,
            &amp;quot;Sequence&amp;quot;:1,
            &amp;quot;BatchResponse&amp;quot;: {
                &amp;quot;Thread&amp;quot;: {
                    //This looks like the Thread Create response
                }
            }
        }
    ]
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now in the SDK you don&amp;#39;t have to work with the raw response. &amp;nbsp;Like other requests with the exception of the file request it supports all the previously mentioned response types. &amp;nbsp;Understanding the structure does help however understand how to use the dynamic response. &amp;nbsp;So given the request above here is how you interact with the response which will be an array:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;Console.WriteLine(&amp;quot;User Request Response Code:&amp;quot; + response.BatchResponses[0].StatusCode);
Console.WriteLine(&amp;quot;User Id:&amp;quot; + response.BatchResponses[0].BatchResponse.User.Id);

Console.WriteLine(&amp;quot;Thread Create Request Response Code:&amp;quot; + response.BatchResponses[1].StatusCode);
Console.WriteLine(&amp;quot;Thread Id:&amp;quot; + response.BatchResponses[1].BatchResponse.Thread.Id);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;An important note is that if you ran the request sequentially, if 1 request fails it considers the entire request a failure and does not process further.&lt;/p&gt;
&lt;h2&gt;&lt;a id="Using_Async" name="Using_Async"&gt;&lt;/a&gt;Using Async&lt;/h2&gt;
&lt;p&gt;If your app uses async programming you can use the SDK&amp;#39;s async methods. &amp;nbsp;For every REST request method there is a corresponding Async version. &amp;nbsp; To learn more about the async pattern see &lt;a href="https://msdn.microsoft.com/en-us/library/hh191443.aspx" rel="noopener noreferrer" target="_blank"&gt;MSDN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here is a simple async method that returns a user Id:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;private async Task&amp;lt;int&amp;gt; GetUserId(string username)
{
    var host = GetHost();
    var pathParameters = new NameValueCollection()
    {
       {&amp;quot;username&amp;quot;, username}
    };
    
   dynamic response = await host.GetToDynamicAsync(2, &amp;quot;users/{username}.json&amp;quot;, true, new RestGetOptions()
   {
       PathParameters = pathParameters
    });

    return Task.FromResult(response.User.Id);
}&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: REST&lt;/div&gt;
</description></item><item><title>Basic Requests</title><link>https://community.telligent.com/community/11/w/developer-training/65137/basic-requests/revision/1</link><pubDate>Thu, 13 Jun 2019 19:35:00 GMT</pubDate><guid isPermaLink="false">8f68fa04-8bd9-4fba-96e0-23f93df30279</guid><dc:creator>Ben Tiedt</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65137/basic-requests#comments</comments><description>Revision 1 posted to Developer Training by Ben Tiedt on 06/13/2019 19:35:00&lt;br /&gt;
&lt;p&gt;Making requests is dependent on understanding [[Hosts]]. &amp;nbsp;The functionality described here is common for all types of hosts but is inaccessible without instantiating or retrieving a host depending on the type of host in use. &amp;nbsp;It is recommended that you review the material on [[Hosts]], [[Client Credentials REST Host]] and [[Default REST Host]] before continuing with this topic.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;For the purposes of the examples in this topic we will be using the [[Client Credentials REST Host]]. &amp;nbsp;However its important to note that the process of making requests to REST is identical for any host once you have obtained an instance of the host.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2&gt;&lt;a id="Types_Of_Requests" name="Types_Of_Requests"&gt;&lt;/a&gt;Types Of Requests&lt;/h2&gt;
&lt;p&gt;The SDK allows for the same types of requests that the REST API supports. &amp;nbsp;These include GET, POST, PUT, DELETE as well as issuing Batch and Widget rendering requests. &amp;nbsp; You can access any REST Url your community currently supports. &amp;nbsp;If you try to make a request to a URL that your&amp;nbsp;community doesn&amp;#39;t support, for instance one only available in a newer version, it will fail. &amp;nbsp; The important reason for mentioning this is the SDK itself doesn&amp;#39;t understand what an endpoint is or does, it simply sees it as a REST Url that will respond with the appropriate payload.&lt;/p&gt;
&lt;h2&gt;&lt;a id="Types_Of_Responses" name="Types_Of_Responses"&gt;&lt;/a&gt;Types Of Responses&lt;/h2&gt;
&lt;p&gt;This is where the SDK earns its stripes. &amp;nbsp;When it comes to the community REST API, there are only 4 types of responses. &amp;nbsp;The 2 most common are XML or JSON. &amp;nbsp;Additionally some endpoints can return you raw binary data or even html data. &amp;nbsp;The SDK &amp;nbsp;can handle all of these and in some cases can give you a helping hand by parsing the response into a more useable &amp;nbsp;format. &amp;nbsp;These are the response types that are available in the SDK and when or how they can be used:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;String&lt;/strong&gt; - &amp;nbsp;This works for either a JSON or XML request. &amp;nbsp;In this case the JSON or XML payload is returned as a string. &amp;nbsp;This is also used if you are using an html based endpoint like the widget rendering endpoint.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stream&lt;/strong&gt; - This basically is returning you the response stream. &amp;nbsp;It works for all types of&amp;nbsp;calls. &amp;nbsp;You especially need this if your payload is raw binary data. &amp;nbsp;Otherwise you can read the stream into any appropriate form.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://msdn.microsoft.com/en-us/library/system.xml.linq.xelement(v=vs.110).aspx" rel="noopener noreferrer" target="_blank"&gt;XElement&lt;/a&gt;&lt;/strong&gt; - &amp;nbsp;This is only available when the REST API is responding with XML. &amp;nbsp;In this case the XML is read into an easy to use .NET XElement object.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://msdn.microsoft.com/en-us/library/dd264736.aspx" rel="noopener noreferrer" target="_blank"&gt;dynamic&lt;/a&gt;&lt;/strong&gt; - This can only be used with JSON response types because it&amp;#39;s the JSON that gets parsed into a dynamic object. &amp;nbsp;A dynamic object essentially allows you to work with the response like its was a strongly typed object without the actual need to create one.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;For each request type, you will find a method for each response type, with the exception of widget rendering which is essentially a GET request.&lt;/p&gt;
&lt;h2&gt;&lt;a id="Getting_Started" name="Getting_Started"&gt;&lt;/a&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;As has been mentioned it&amp;#39;s a host that gives you access to make REST calls. For the purposes of example this topic uses the [[Client Credentials REST Host]] but it is important to re-iterate that the calls illustrated in this topic are identical regardless of host, the only variance is how the host&amp;nbsp;is retrieved. &amp;nbsp; If you would like to try any of these examples you can create a new console application in Visual Studio then install the SDK as described [[REST SDK|here]].&lt;/p&gt;
&lt;h3&gt;&lt;a id="Loading_up_a_Host" name="Loading_up_a_Host"&gt;&lt;/a&gt;Loading up a Host&lt;/h3&gt;
&lt;p&gt;In our examples we have a simple method to load our host to avoid repetitive code. &amp;nbsp;You can do this inline as well if you choose. &amp;nbsp;You will also need to ensure you have setup an Oauth client that is private with a Client Credentials grant type. The urls can be whatever you want, they are not relevant using client credentials. &amp;nbsp;If you are unsure&amp;nbsp;how to do this refer to the OAuth section of the REST API&amp;#39;s [[Authentication]] topic.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;private static ClientCredentialsRestHost GetHost()
{
    return new ClientCredentialsRestHost(&amp;quot;admin&amp;quot;
        ,&amp;quot;http://yoursiteurl.com&amp;quot;
        , &amp;quot;[Your Client Id]&amp;quot;
        , &amp;quot;[Your Client Secret]&amp;quot;);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If you were using the [[Default REST Host]] you can use the same pattern with a small adjustment, assuming you have set it up correctly. &amp;nbsp; After this all the REST requests work exactly the same.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;private static Host GetHost()
{
     return Host.Get(&amp;quot;default&amp;quot;);
}&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Building_a_Request" name="Building_a_Request"&gt;&lt;/a&gt;Building a Request&amp;nbsp;&lt;/h2&gt;
&lt;p&gt;The way you make the types of requests with the types of responses we have discussed is through invoking particular methods on the host. &amp;nbsp;The naming pattern is constant for all of them so for each request type, there is an option for a different response type. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;Given this list of request types, essentially here is the available methods:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Host.GetTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;](...)&lt;/li&gt;
&lt;li&gt;Host.PostTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;](...)&lt;/li&gt;
&lt;li&gt;Host.PutTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;](...)&lt;/li&gt;
&lt;li&gt;Host.DeleteTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;](...)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally each of those has an async counterpart which we will cover more in depth later:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Host.GetTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;]Async(...)&lt;/li&gt;
&lt;li&gt;Host.PostTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;]Async(...)&lt;/li&gt;
&lt;li&gt;Host.PutTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;]Async(...)&lt;/li&gt;
&lt;li&gt;Host.DeleteTo[&lt;em&gt;Dynamic|String|Stream|XElement&lt;/em&gt;]Async(...)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a id="Anatomy_of_a_Request" name="Anatomy_of_a_Request"&gt;&lt;/a&gt;Anatomy of a Request&lt;/h3&gt;
&lt;p&gt;Every request requires a minimum of 2 pieces of information with the exception of the batch request which will be covered separately. &amp;nbsp; These are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;REST Version&lt;/strong&gt; - &amp;nbsp;This is the endpoint version. &amp;nbsp;If you were making a request manually it is part of the url (/api.ashx/v&lt;strong&gt;2&lt;/strong&gt;/...). &amp;nbsp;In the SDK the number from this required as the first argument.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Url&lt;/strong&gt; - This is the actual endpoint you are trying to contact WITHOUT /&lt;em&gt;api.ashx/v2/&lt;/em&gt;. &amp;nbsp; The&amp;nbsp;SDK will build this part of the url automatically using the version in the first argument.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Given this if we wanted to produce a GET request that required no parameters it would look like this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var host = GetHost();
var response = host.GetToDynamic(2, &amp;quot;info.json&amp;quot;);&lt;/pre&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Impersonation" name="Impersonation"&gt;&lt;/a&gt;Impersonation&lt;/h3&gt;
&lt;p&gt;Each request method gives you the ability to opt-in or out of impersonation. This however only works if the host you are using supports impersonation. &amp;nbsp;While it&amp;#39;s recommended that a host supports impersonation, it may not. &amp;nbsp;You should refer to your host&amp;#39;s documentation on how it handles impersonation of another user if at all. &amp;nbsp;If you know you do not wish to impersonate, you should pass in false for the enableImpersonation parameter. &amp;nbsp;The enableImpersonation argument is optional and when not supplied defaults to true.&lt;/p&gt;
&lt;p&gt;Consult the topic on the [[Client Credentials REST Host]] and [[Default REST Host]] for how this parameter is used and how they support impersonation.&lt;/p&gt;
&lt;p&gt;The following calls both will tell the host to use impersonation if its supported:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var host = GetHost();
var response = host.GetToDynamic(2, &amp;quot;info.json&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;OR&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var host = GetHost();
var response = host.GetToDynamic(2, &amp;quot;info.json&amp;quot;,true); //addition of &amp;quot;enableImpersonation&amp;quot; parameter&lt;/pre&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Options_Objects" name="Options_Objects"&gt;&lt;/a&gt;Options Objects&lt;/h3&gt;
&lt;p&gt;Options objects are classes passed in to each type of request that can have several optional arguments. This is also where additional optional arguments would be added in the future. &amp;nbsp;Options themselves are also&amp;nbsp;optional.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Querystring_Parameters" name="Querystring_Parameters"&gt;&lt;/a&gt;Querystring Parameters&lt;/h4&gt;
&lt;p&gt;Querystring parameters are parameters appended to the REST Url after a &amp;#39;?&amp;#39; symbol. &amp;nbsp;They are the most common on GET requests but are supported on all the request types. &amp;nbsp;You do not need to actually add them to the url yourself, instead if you evaluate the options object on the method you are calling you should find a property to add query string parameters.&lt;/p&gt;
&lt;p&gt;The following example illustrates a GET call using querystring parameters. &amp;nbsp;The pattern is the same for POST,PUT and DELETE requests as well.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var host = GetHost();

var querystring = new NameValueCollection();
querystring.Add(&amp;quot;pageSize&amp;quot;,&amp;quot;20&amp;quot;);
querystring.Add(&amp;quot;pageIndex&amp;quot;,&amp;quot;1&amp;quot;);

var response = host.GetToDynamic(2, &amp;quot;users.json&amp;quot;,true,new RestGetOptions()
{
    QueryStringParameters = querystring
});&lt;/pre&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="Path_Parameters" name="Path_Parameters"&gt;&lt;/a&gt;Path Parameters&lt;/h4&gt;
&lt;p&gt;Like querystring parameters path parameters are used to add dynamic data to a request however unlike querystring parameters these aren&amp;#39;t added to anything, rather they are substitution values, ususally meant to replace a value in the url.&lt;/p&gt;
&lt;p&gt;The substitution value is a key name surrounded by {}. &amp;nbsp;For example the key userid is a path parameter in the following url:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;users/{userid}.json&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;A path parameter can be at any position in the url string. &amp;nbsp; To define a value for a parameter you pass it in to the PathParameters of the options object. &amp;nbsp;PathParameters are supported on all GET,POST,PUT and DELETE requests. &amp;nbsp;You can define your own path parameter as well, as long as it is provided a value in the PathParameters collection.&lt;/p&gt;
&lt;p&gt;This example uses PathParameters in a simple GET.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var host = GetHost();
 
var pathParameters = new NameValueCollection();
pathParameters.Add(&amp;quot;userid&amp;quot;, &amp;quot;2100&amp;quot;);

var response = host.GetToDynamic(2, &amp;quot;users/{userid}.json&amp;quot;, true, new RestGetOptions()
{
   PathParameters = pathParameters
});&lt;/pre&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="Post_Parameters" name="Post_Parameters"&gt;&lt;/a&gt;Post Parameters&lt;/h4&gt;
&lt;p&gt;Unlike the other parameter types, PostParameters&amp;nbsp;are added to the request body rather than be part of the url. &amp;nbsp;These types of parameters are only supported for POST and PUT requests. &amp;nbsp; The following user creation method passes PostParameters:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var host = GetHost();

var postParameters = new NameValueCollection();
postParameters.Add(&amp;quot;Username&amp;quot;,&amp;quot;somerandomusername&amp;quot;);
postParameters.Add(&amp;quot;PrivateEmail&amp;quot;, &amp;quot;somerandomusername@localhost.com&amp;quot;);
postParameters.Add(&amp;quot;Password&amp;quot;,&amp;quot;SuperComplexPassword&amp;quot;);

var response = host.PostToDynamic(2, &amp;quot;users.json&amp;quot;, true, new RestPostOptions()
{
    PostParameters = postParameters
});&lt;/pre&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="Custom_Headers" name="Custom_Headers"&gt;&lt;/a&gt;Custom Headers&lt;/h4&gt;
&lt;p&gt;If for some reason you require custom headers from your application you can specify them on the options object. &amp;nbsp;This will also overwrite existing headers. &amp;nbsp;This should be supported on all request options objects.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var customHeaders = new NameValueCollection()
{
    {&amp;quot;X-App-Name&amp;quot;,&amp;quot;MyCustomApp&amp;quot;}
};

dynamic response = host.GetToDynamic(2, &amp;quot;info.json&amp;quot;, true, new RestGetOptions()
{
  AdditionalHeaders = customHeaders
});&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Handling_a_Response" name="Handling_a_Response"&gt;&lt;/a&gt;Handling a Response&lt;/h2&gt;
&lt;p&gt;Most of the response types are fairly straight forward and dealing with them is not really specific to using the SDK. &amp;nbsp;Here are the response types and how your code can potentially handle them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://msdn.microsoft.com/en-us/library/system.xml.linq.xelement(v=vs.110).aspx"&gt;XElement&lt;/a&gt; - &amp;nbsp;This gives you a .NET XElement object representing XML. &amp;nbsp;Using this element you can read the data using&lt;a href="https://msdn.microsoft.com/en-us/library/bb387098.aspx" rel="noopener noreferrer" target="_blank"&gt; LINQ to Xml &lt;/a&gt;queries.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stream&lt;/strong&gt; - There are different paths for streams depending on the payload. &amp;nbsp;For XML or JSON the stream can be read into memory and then used to deserialize the data into classes you have created in your application. &amp;nbsp;If the payload is a file you can read the stream into the appropriate file and save it to disk. &amp;nbsp;Generally you would not use stream to convert to a string because that option is already available.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;String&lt;/strong&gt; - This is most appropriate for Html or JSON return types. &amp;nbsp; You can use the string to output html directly or it can be used for JSON serialization or manipulation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last probably most powerful response is &lt;a href="https://msdn.microsoft.com/en-us/library/dd264741.aspx"&gt;dynamic&lt;/a&gt;&amp;nbsp;and while it is also not an SDK specific response type, its worth spending a bit more time on since&amp;nbsp;its relatively new. &amp;nbsp;The downside with these is that unlike strongly typed classes, there is no Intellisense help when writing code.&lt;/p&gt;
&lt;p&gt;You interact wth dynamics just like a class, by accessing its properties. &amp;nbsp;The difference however is that the properties &amp;nbsp;aren&amp;#39;t actually defined, they are dynamically bound at runtime.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A simple&amp;nbsp;example would be if you had a plain old object called &amp;quot;Foo&amp;quot; and you in your code you called the property &amp;quot;Name&amp;quot;. &amp;nbsp;If your Foo object does not&amp;nbsp;have a property called &amp;quot;Name&amp;quot;, your code will not compile. &amp;nbsp;This is because the compiler checks for these types of errors when compiling. &amp;nbsp;If Foo is type dynamic and you called Foo.Name the code would compile without error. &amp;nbsp;This is because this reference is ignored by the compiler for dynamics until runtime. &amp;nbsp; Using this concept we do not have to write a class for every possible response from the REST API. &amp;nbsp;We simply take the response and convert it to a type of dynamic. &amp;nbsp;This means you can code against the properties &amp;nbsp;even though the code does not yet know if a property exists yet. &amp;nbsp;Only after its evaluated at runtime if the property does not exist will it throw an error.&lt;/p&gt;
&lt;p&gt;We base the dynamic binding on the hierarchal structure of the JSON response so you can only use dynamic responses with JSON requests. &amp;nbsp;Review this JSON response(this response has been shortened for example purposes):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="json"&gt;{
  &amp;quot;InfoResult&amp;quot;: {
    &amp;quot;SiteName&amp;quot;: &amp;quot;sitename&amp;quot;,
    &amp;quot;SiteDescription&amp;quot;: &amp;quot;sitedescription&amp;quot;,
  },
  &amp;quot;AccessingUser&amp;quot;: {
    &amp;quot;ContentId&amp;quot;: &amp;quot;49fec544-6df7-4a82-872b-f8be586d5e9e&amp;quot;,
    &amp;quot;ContentTypeId&amp;quot;: &amp;quot;9f5a6721-639d-4e1d-ab6a-ce63b7750f46&amp;quot;,
    &amp;quot;DisplayName&amp;quot;: &amp;quot;displayname&amp;quot;,
    &amp;quot;Username&amp;quot;: &amp;quot;username&amp;quot;,
    &amp;quot;Id&amp;quot;: 6
  },
  &amp;quot;Errors&amp;quot;: [
    &amp;quot;string&amp;quot;,
    &amp;quot;string&amp;quot;
  ]
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In this example, InfoResult would be &amp;nbsp;a property of the dynamic object and Sitename would be a property of InfoResult. &amp;nbsp; Similarly AccessingUser is a property on the dynamic object and Username is a property of Accessing User.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;pre class="ui-code" data-mode="csharp"&gt;var host = GetHost();
var response = host.GetToDynamic(2, &amp;quot;info.json&amp;quot;);

Console.WriteLine(&amp;quot;Site Name:&amp;quot; + response.InfoResult.SiteName);
Console.WriteLine(&amp;quot;Accessing Username:&amp;quot; + response.AccessingUser.Username);&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Uploading_a_File" name="Uploading_a_File"&gt;&lt;/a&gt;Uploading a File&lt;/h2&gt;
&lt;p&gt;The SDK also supports uploading files to use as attachments to other pieces of contents. &amp;nbsp;The advantage of the SDK upload is it is similar to how you upload files in the UI. &amp;nbsp;If the file is under 15mb the whole file is sent, otherwise it is broken up into 15mb chunks and transmitted individually. &amp;nbsp;This bypasses request limits and helps avoid timeouts by spreading the file out over multiple requests. &amp;nbsp; Unlike other requests this will give you a strongly typed UploadedFileInfo argument back&amp;nbsp;in lieu of the other types of responses already discussed.&lt;/p&gt;
&lt;p&gt;Here is an example of a file upload in its most basic form&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using (var fileStream = new FileStream(&amp;quot;c:\\test.png&amp;quot;, FileMode.Open, FileAccess.Read))
{
   fileStream.Position = 0;
   Guid uploadContextId = Guid.NewGuid();
   UploadedFile file = new UploadedFile(uploadContextId, &amp;quot;test.png&amp;quot;, &amp;quot;image/png&amp;quot;, fileStream);

   UploadedFileInfo response = host.UploadFile(file);
   if (!response.IsError)
      Console.WriteLine(response.UploadContext);
   else
      Console.WriteLine(response.Message);
 }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;You can also track the progress of each chunk using the UploadProgess action on the delegate that will give you FileUploadProgress object to interact with. &amp;nbsp;Below we will print the percent complete.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using (var fileStream = new FileStream(&amp;quot;c:\\test.png&amp;quot;, FileMode.Open, FileAccess.Read))
{
   fileStream.Position = 0;
   Guid uploadContextId = Guid.NewGuid();
   UploadedFile file = new UploadedFile(uploadContextId, &amp;quot;test.png&amp;quot;, &amp;quot;image/png&amp;quot;, fileStream);

   UploadedFileInfo response = host.UploadFile(file,new RestFileOptions()
   {
       UploadProgress = (p) =&amp;gt;
          {
             Console.WriteLine(&amp;quot;Percent Complete:&amp;quot; + p.PercentComplete);
          }
    });
    
    if (!response.IsError)
         Console.WriteLine(response.UploadContext);
   else
         Console.WriteLine(response.Message);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;You can use that file to create an attachment to something like a forum thread using the context Id you specified:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using (var fileStream = new FileStream(&amp;quot;c:\\test.png&amp;quot;, FileMode.Open, FileAccess.Read))
{
    fileStream.Position = 0;
    Guid uploadContextId = Guid.NewGuid();
    UploadedFile file = new UploadedFile(uploadContextId, &amp;quot;test.png&amp;quot;, &amp;quot;image/png&amp;quot;, fileStream);

    UploadedFileInfo fileInfo = host.UploadFile(file,new RestFileOptions()
    {
        UploadProgress = (p) =&amp;gt;
        {
            Console.WriteLine(&amp;quot;Percent Complete:&amp;quot; + p.PercentComplete);
        }
    });
    
    f (!fileInfo.IsError)
    {
        var pathParameters = new NameValueCollection();
        pathParameters.Add(&amp;quot;forumid&amp;quot;,&amp;quot;2958&amp;quot;);

        var postParameters = new NameValueCollection();
       postParameters.Add(&amp;quot;Subject&amp;quot;,&amp;quot;This is a cool Forum&amp;quot;);
       postParameters.Add(&amp;quot;Body&amp;quot;,&amp;quot;I think I will post a thread in it&amp;quot;);
                        
        //Now add the file
        postParameters.Add(&amp;quot;FileName&amp;quot;, &amp;quot;test.png&amp;quot;);
       postParameters.Add(&amp;quot;ContentType&amp;quot;, &amp;quot;image/png&amp;quot;);
       postParameters.Add(&amp;quot;FileUploadContext&amp;quot;,fileInfo.UploadContext.ToString());//Use the upload context Id from our file upload


        dynamic threadResponse = host.PostToDynamic(2, &amp;quot;forums/{forumid}/threads.json&amp;quot;, true,
            new RestPostOptions()
            {
                PathParameters = pathParameters,
                PostParameters = postParameters
           });
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Batching" name="Batching"&gt;&lt;/a&gt;Batching&lt;/h2&gt;
&lt;p&gt;Batch requests are making several REST requests in a single call. &amp;nbsp;This reduces overhead because only the batch request is processed over HTTP, the containing requests are executed in process on the server. &amp;nbsp;The SDK makes batch requests easier as well since you don&amp;#39;t have to know the request format like you do making a batch request against REST&amp;nbsp;directly.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A batch request is a collection of batch request objects translated into individual requests before being sent to community.. &amp;nbsp; Batch request objects contain similar information to a single request method with a couple of exceptions. &amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The default APIVersion will always be &lt;strong&gt;2&lt;/strong&gt; though there is an &lt;strong&gt;APIVersion&lt;/strong&gt; property to override this value.&lt;/li&gt;
&lt;li&gt;Each request must have a sequence specified in the constructor, the sequence is a zero based so your first sequence value should be 0.**&lt;/li&gt;
&lt;li&gt;You must specify that a request is GET,POST etc in the &lt;strong&gt;RestMethod&lt;/strong&gt; property since a batch request itself is a POST.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;QueryString&lt;/strong&gt; and &lt;strong&gt;PostParameters&lt;/strong&gt; that you are used to in previous requests are collapsed into a single collection called RequestParameters and are used querystring or body parameters depending on the RestMethod. &amp;nbsp;PathParameters are separate and work the same.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;**Sequence is always required but only honored when a batch request is set to be sequential. &amp;nbsp;Otherwise the requests are processed in parallel on the server.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The following example executes a GET and POST request in a single request in parallel:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var batchRequestList = new List&amp;lt;BatchRequest&amp;gt;();
var userRequest = new BatchRequest(&amp;quot;users/{username}.json&amp;quot;, 0);
userRequest.RestMethod = RestMethod.GET;
serRequest.PathParameters = new NameValueCollection()
{
    {&amp;quot;username&amp;quot;,&amp;quot;pmason&amp;quot;}
};
batchRequestList.Add(userRequest);

var threadRequest = new BatchRequest(&amp;quot;forums/{forumid}/threads.json&amp;quot;, 1);
threadRequest.RestMethod = RestMethod.POST;
threadRequest.PathParameters = new NameValueCollection()
{
    {&amp;quot;forumid&amp;quot;,&amp;quot;2958&amp;quot;}
};

threadRequest.RequestParameters = new NameValueCollection()
{
    {&amp;quot;Subject&amp;quot;,&amp;quot;This is a great thread&amp;quot;},
    {&amp;quot;Body&amp;quot;,&amp;quot;I love this forum so much!&amp;quot;}
};
batchRequestList.Add(threadRequest);

dynamic response = host.BatchRequestToDynamic(2, batchRequestList, true);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;You can force &amp;nbsp;this to run sequentially, meaning each request will be run in order of its sequence value, by adding the options argument and setting the RunSequentially flag:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;dynamic response = host.BatchRequestToDynamic(2, batchRequestList, true,new BatchRequestOptions()
{
   RunSequentially = true
});&lt;/pre&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Batch responses are similar to the request, where you will get back a collection of the responses. &amp;nbsp; Each response has metadata about the response including the response code and then a BatchResponse property which is the response data returned from the request endpoint. &amp;nbsp;This data is identical to the format of the endpoint had it been done in a single request.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="json"&gt;{
    &amp;quot;BatchResponses&amp;quot;:[
        {
            &amp;quot;Url&amp;quot;: &amp;quot;api.ashx/v2/users/pmason.json&amp;quot;,
            &amp;quot;StatusCode&amp;quot;: 200,
            &amp;quot;Sequence&amp;quot;: 0,
            &amp;quot;BatchResponse&amp;quot;: {
                &amp;quot;User&amp;quot;: {
                    //This looks like the user SHOW response
                }
            }
        },
        {
            &amp;quot;Url&amp;quot;:&amp;quot;api.ashx/v2/forums/2958/threads.json&amp;quot;, 
            &amp;quot;StatusCode&amp;quot;:200,
            &amp;quot;Sequence&amp;quot;:1,
            &amp;quot;BatchResponse&amp;quot;: {
                &amp;quot;Thread&amp;quot;: {
                    //This looks like the Thread Create response
                }
            }
        }
    ]
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now in the SDK you don&amp;#39;t have to work with the raw response. &amp;nbsp;Like other requests with the exception of the file request it supports all the previously mentioned response types. &amp;nbsp;Understanding the structure does help however understand how to use the dynamic response. &amp;nbsp;So given the request above here is how you interact with the response which will be an array:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;Console.WriteLine(&amp;quot;User Request Response Code:&amp;quot; + response.BatchResponses[0].StatusCode);
Console.WriteLine(&amp;quot;User Id:&amp;quot; + response.BatchResponses[0].BatchResponse.User.Id);

Console.WriteLine(&amp;quot;Thread Create Request Response Code:&amp;quot; + response.BatchResponses[1].StatusCode);
Console.WriteLine(&amp;quot;Thread Id:&amp;quot; + response.BatchResponses[1].BatchResponse.Thread.Id);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;An important note is that if you ran the request sequentially, if 1 request fails it considers the entire request a failure and does not process further.&lt;/p&gt;
&lt;h2&gt;&lt;a id="Using_Async" name="Using_Async"&gt;&lt;/a&gt;Using Async&lt;/h2&gt;
&lt;p&gt;If your app uses async programming you can use the SDK&amp;#39;s async methods. &amp;nbsp;For every REST request method there is a corresponding Async version. &amp;nbsp; To learn more about the async pattern see &lt;a href="https://msdn.microsoft.com/en-us/library/hh191443.aspx" rel="noopener noreferrer" target="_blank"&gt;MSDN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here is a simple async method that returns a user Id:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;private async Task&amp;lt;int&amp;gt; GetUserId(string username)
{
    var host = GetHost();
    var pathParameters = new NameValueCollection()
    {
       {&amp;quot;username&amp;quot;, username}
    };
    
   dynamic response = await host.GetToDynamicAsync(2, &amp;quot;users/{username}.json&amp;quot;, true, new RestGetOptions()
   {
       PathParameters = pathParameters
    });

    return Task.FromResult(response.User.Id);
}&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item></channel></rss>