Just an FYI on this... I was able to generate a C# client to call a MAS REST API (as well as a SASBIWS json stored process). MAS appears to be quite a bit faster for scoring a simple sample model but that's irrelevant to this specific topic. For MAS, I first generate a ticket; (by HTTP Post to: https://SERVER/SASLogon/rest/VERSION/tickets with UID and PWD parameters... which returns a pre-authenticated URL in a "Location" header; calling that via another http post returns a ticket that can temporarily be used for subsequent calls). So, I do that and set a breakpoint in Visual Studio order to grab the ticket... then tried NSwagStudio, looking to auto-generate implementation classes... so, basically, targeting this in NSwagStudio... https://SERVER/SASMicroAnalyticService/rest/modules/MODEL/steps/execute?ticket=TICKET (where SERVER = my midtier server, and MODEL = the name of what I deployed to MAS from Decision Builder)... ... I was then able to pull a bunch of .json into Swagger... but, unfortunately, it is not in a format for which Swagger can automatically parse and generate C# client classes. However, it does pretty print ths json, and based on that it was pretty straight-forward to manually implement a generic "ScoringOutput" class, and to map it using a combination of RESTSharp (to make the calls to MAS) and Newtonsoft Json.Net, for parsing the resulting json. Here's what I did: The "SAS_ScoringOutput" class: class SAS_ScoringOutput
{
public String moduleId = "";
public String moduleName = "";
public String stepId = "";
public IList<SAS_Mappings.SAS_Links> links = new List<SAS_Mappings.SAS_Links>();
public Int64 version = 0;
public IList<SAS_Mappings.SAS_NameValuePair> output = new List<SAS_Mappings.SAS_NameValuePair>();
} which uses two other helper classes... class SAS_Links
{
public String method;
public String rel;
public String href;
public String uri;
public String type;
} ...and... class SAS_NameValuePair
{
public String name = "";
public String value = "";
public SAS_NameValuePair(String pName, String pValue)
{
name = pName;
value = pValue;
}
} Given all that, and references to both RESTSharp and Json.Net, and a valid ticket... the following should work: private static SAS_ScoringOutput CallModelScoring(String sasTicket)
{
SAS_ScoringOutput jsonRsp = null;
// 1. build the request
StringBuilder jsonRequest = new StringBuilder(""); // build your json request here... system dependent
IRestClient rstClient1 = new RestClient();
rstClient1.BaseUrl = new Uri("https://SERVER/SASMicroAnalyticService/rest/modules/MODEL/steps/execute?ticket=" + sasTicket);
rstClient1.CookieContainer = new System.Net.CookieContainer();
IRestRequest rstReq1 = new RestSharp.RestRequest();
rstReq1.Method = Method.POST;
rstReq1.AddHeader("Accept", "*/*");
rstReq1.Parameters.Clear();
rstReq1.AddParameter(
"application/json",
jsonRequest.ToString(),
ParameterType.RequestBody);
// 2. Make the Call
IRestResponse rstRsp1 = rstClient1.Execute(rstReq1);
// 3. Process Results
Newtonsoft.Json.Linq.JObject jo = Newtonsoft.Json.Linq.JObject.Parse(rstRsp1.Content);
jsonRsp = new SAS_ScoringOutput();
jsonRsp.moduleId = jo.SelectToken("moduleId").ToString();
jsonRsp.moduleName = jo.SelectToken("moduleName").ToString();
jsonRsp.stepId = jo.SelectToken("stepId").ToString();
jsonRsp.version = long.Parse(jo.SelectToken("version").ToString());
foreach (Newtonsoft.Json.Linq.JToken jt in jo.SelectToken("output").Children())
{
jsonRsp.output.Add(new SAS_NameValuePair(jt.SelectToken("name").ToString(), jt.SelectToken("value").ToString()));
}
return jsonRsp;
} There are C# predicate tricks that could reduce the lines of code, and probably other code improvements that could be made, but you get the idea. Also, my names/values are always String... for a model that returns int/double/boolean/date type parameters, you'll have to do the appropriate conversions when mapping your SAS_ScoringOutput class back into the consuming application code layers. Anyway, hope that helps, if anyone's working on something similar.
... View more