Smart Encapsulation from similar objects - c#

I have a few Soap-requests that all start the same:
First request:
var client = new Conn.Team.z_proj_team_spQueryPortClient();
client.Endpoint.Address = EndPoint;
var query = new Conn.Team.z_proj_team_spQuery
{
Filter = new Conn.Team.z_proj_team_spFilter
{
param_code = projectCode
}
};
var auth = new Conn.Team.Auth { Username = _username, Password = _password };
var records = client.Query(auth, query).Records;
second request:
var client = new Conn.Task.z_proj_Task_spQueryPortClient();
client.Endpoint.Address = EndPoint;
var query = new Conn.Task.z_proj_Task_spQuery
{
Filter = new Conn.Task.z_proj_Task_spFilter
{
param_code = projectCode
}
};
var auth = new Conn.Task.Auth { Username = _username, Password = _password };
var records = client.Query(auth, query).Records;
As you can see, the code looks nearly the same, but these are completely different objects (that do not share a base class) but who use the same property-names.
Because I have about 10 of these calls, is there a good way to wrap these functions? Would you even advice to do so or would Reflection simple makes it "more evil"?
(BTW:) I am unsure what a good tag would be for my problem. Feel free to change them to better ones

Solved this the following "reflection/dynamic" way. Feel free to post a better solution if you have one.
private object Connect(Type clientType, Type queryType, Type filterType, Type authType, string code)
{
dynamic client = Activator.CreateInstance(clientType);
client.Endpoint.Address = EndPoint;
dynamic query = Activator.CreateInstance(queryType);
dynamic filter = Activator.CreateInstance(filterType);
filter.param_code = code;
query.Filter = filter;
dynamic auth = Activator.CreateInstance(authType);
auth.Username = _username;
auth.Password = _password;
return client.Query(auth, query).Records;
}

Related

Consume and Configure Graphql request from .Net C# console application client

I'm trying to consume a Graphql Api from a C# client. For that I'm using the GraphQl.Net Nuget package. The problem is that, I have no idea how to set the Api Url as I don't have HttpRequest object and this results also with additional problems that I can't set the authentcation header and send the token with the request. My code looks like:
public void Post(TestGraphQl.GraphQLQuery query)
{
var inputs = query.Variables.ToInputs();
var queryToExecute = query.Query;
var result = _executer.ExecuteAsync(_ =>
{
_.Schema = _schema;
_.Query = queryToExecute;
_.OperationName = query.OperationName;
_.Inputs = inputs;
//_.ComplexityConfiguration = new ComplexityConfiguration { MaxDepth = 15 };
_.FieldMiddleware.Use<InstrumentFieldsMiddleware>();
}).Result;
var httpResult = result.Errors?.Count > 0
? HttpStatusCode.BadRequest
: HttpStatusCode.OK;
var json = _writer.Write(result);
}
And the caller looks like this:
var jObject = new Newtonsoft.Json.Linq.JObject();
jObject.Add("id", deviceId);
client.Post(new GraphQLQuery { Query = "query($id: String) { device (id: $id) { displayName, id } }", Variables = jObject });
I'm totally new to this topic and appreciate any help. Many thanks!!
This worked out for me. You will need the GraphQL.Client Package. My_class is the class for the deserialization.
var client = new GraphQLHttpClient(Api_Url, new NewtonsoftJsonSerializer());
var request = new GraphQLRequest
{
Query = {query}
};
var response = await client.SendQueryAsync<my_class>(request);
Not sure if you are still looking for it. One can always use GraphQl.Client nuget to achieve this. Sample code to consume is
var query = #"query($id: String) { device (id: $id) { displayName, id } }";
var request = new GraphQLRequest(){
Query = query,
Variables = new {id =123}
};
var graphQLClient = new GraphQLClient("http://localhost:8080/api/GraphQL");
graphQLClient.DefaultRequestHeaders.Add("Authorization", "yourtoken");
var graphQLResponse = await graphQLClient.PostAsync(request);
Console.WriteLine(graphQLResponse.Data);

Making DialogFlow v2 DetectIntent Calls w/ C# (including input context)

So I finally figured out a way to successfully make detect intent calls and provide an input context. My question is whether or not this is the CORRECT (or best) way to do it:
(And yes, I know you can just call DetectIntent(agent, session, query) but I have to provide a input context(s) depending on the request)
var query = new QueryInput
{
Text = new TextInput
{
Text = model.Content,
LanguageCode = string.IsNullOrEmpty(model.Language) ? "en-us" : model.Language,
}
};
var commonContext = new global::Google.Cloud.Dialogflow.V2.Context
{
ContextName = new ContextName(agent, model.sessionId, "my-input-context-data"),
LifespanCount = 3,
Parameters = new Struct
{
Fields = {
{ "Source", Value.ForString(model.Source) },
{ "UserId" , Value.ForString(model.UserId.ToString())},
{ "Name" , Value.ForString(model.FirstName)}
}
}
};
var request = new DetectIntentRequest
{
SessionAsSessionName = new SessionName(agent, model.sessionId),
QueryParams = new QueryParameters
{
GeoLocation = new LatLng {Latitude = model.Latitude, Longitude = model.Longitude},
TimeZone = model.TimeZone ?? "MST"
},
QueryInput = query
};
request.QueryParams.Contexts.Add(commonContext);
// ------------
var creds = GetGoogleCredentials("myCredentials.json");
var channel = new Grpc.Core.Channel(SessionsClient.DefaultEndpoint.Host, creds.ToChannelCredentials());
var client = SessionsClient.Create(channel);
var response = client.DetectIntent(request);
channel.ShutdownAsync();
return response;
Note: I included the explicit ShutDownAsync (it's not in an async call) because I was getting some file locking issues when attempting to re-deploy the WebAPI project (and only after having executed this code).
Thanks
Chris
Updated 4/25: The most basic way I use this is to integrate the user's name into intent responses:
It can also be read from within the webhook/inline fulfillment index.js:
const name = request.body.queryResult && request.body.queryResult.outputContexts && request.body.queryResult.outputContexts[0].parameters.Name

Xamarin: Using HttpClient POST in combination with a dynamic Class

I have some services that require rather complex objects. Every service uses almost the same base object but it needs to be extended for each service.
A simple example:
The Standard Object would be something like:
ContextObject {
params {
Device {
Name: "MyMobileDevice",
ID: 123455691919238
}
}
}
and for my service I need to add some properties under params,
something like:
ContextObject {
params {
Device {
Name: "MyMobileDevice",
ID: 123455691919238
},
requested_employee_id: 112929
}
}
I tried to get this by using JObject and got it working so far but now I cant find a proper example on how to send this object to my server using HttpClient.
Edit:
Here is my full JObject which all Requests need:
public static JObject DefaultContext (string ServiceMethod) {
var Context = new JObject();
Context["version"] = "1.1";
Context["method"] = ServiceMethod;
Context["params"] = JObject.FromObject( new {
Context = JObject.FromObject( new {
User = App.UserSettings.USERNAME,
Password = App.UserSettings.PASSWORD,
SerialNumber = "1234567890", // TODO: use generated id
Locale = "de-DE",
Timestamp = DateTime.Now.ToString("yyyy-MM-ddTHH\\:mm\\:ss.fffzzz"),
Device = JObject.FromObject( new {
DeviceType = "phone",
ProductType = "D6603", // TODO: Get from Device-Info
screen = JObject.FromObject( new {
Density = "xxhdpi", // TODO: Get from Device-Info
resolution = JObject.FromObject( new {
Height = "1920", // TODO: Get from Device-Info
Width = "1080" // TODO: Get from Device-Info
})
}),
version = JObject.FromObject( new {
AppVersion = "myAppVersion", // TODO: Get App-Information LayoutVersion = "1.0"
} )
})
})
});
return mobileContext;
}
For my Requests I need to add parameters under the "params"-Node. Which works with:
mobileContext["params"]["mynewparameter"] = "FOO";
Now I wanted to send this JObject via System.Net.Http-Client to my server with something like this:
var client = new HttpClient ();
client.BaseAddress = new Uri (App.UserSettings.HOST + ":" + App.UserSettings.PORT + App.UserSettings.TYPE);
client.Timeout = 3000;
var context = MyContext.DefaultContext (ServiceMethods.CUSTOMER_LIST_METHOD);
context ["params"] ["myrequestparam"] = "FOO";
var jsonString = JsonConvert.SerializeObject (context);
var responseData = await client.Get???????
Is my general approach correct? How would you do it? Is there a sample on how to handle such dynamic stuff?
I couldn't find a example on how to use httpclient correctly with the Newtonsoft.JSON-Library how far am I from actually working code?

Code connect to Google Analytics API with C# error

I trying using Google Analytics with C# to get stats information to display in my webiste
Here is my code
public ActionResult Index()
{
string userName = "admin#email.com";
string passWord = "mypass";
string profileId = "ga:xxxxxxxx";
string key = "2d751338cb092ef8da65f716e37a48604386c9sw";
string dataFeedUrl = "https://www.google.com/analytics/feeds/data"+key;
var service = new AnalyticsService("API Project");
service.setUserCredentials(userName, passWord);
var dataQuery = new DataQuery(dataFeedUrl)
{
Ids = profileId,
Metrics = "ga:pageviews",
Sort = "ga:pageviews",
GAStartDate = new DateTime(2010, 3, 1).ToString("yyyy-MM-dd"),
GAEndDate = DateTime.Now.ToString("yyyy-MM-dd")
};
var dataFeed = service.Query(dataQuery);
var totalEntry = dataFeed.Entries[0];
ViewData["Total"] = ((DataEntry)(totalEntry)).Metrics[0].Value;
dataQuery.GAStartDate = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd");
dataQuery.GAEndDate = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd");
dataFeed = service.Query(dataQuery);
var yesterdayEntry = dataFeed.Entries[0];
ViewData["Yesterday"] = ((DataEntry)(yesterdayEntry)).Metrics[0].Value;
dataQuery.GAStartDate = DateTime.Now.ToString("yyyy-MM-dd");
dataQuery.GAEndDate = DateTime.Now.ToString("yyyy-MM-dd");
dataFeed = service.Query(dataQuery);
var todayEntry = dataFeed.Entries[0];
ViewData["Today"] = ((DataEntry)(todayEntry)).Metrics[0].Value;
return View(dataFeed.Entries);
}
But when i run the code it always said "{"Invalid credentials"}"
Not sure why i facing this error while i checked many time about the key,username,password and profileId
Anyone facing this problem,can help me?
Many thanks
I think that your url is wrong. try in this way (you are missing ?key=).
string dataFeedUrl = "https://www.google.com/analytics/feeds/data?key="+key;
refer this google example where there is this example that should help you
public DataFeedExample()
{
// Configure GA API.
AnalyticsService asv = new AnalyticsService("gaExportAPI_acctSample_v2.0");
// Client Login Authorization.
asv.setUserCredentials(CLIENT_USERNAME, CLIENT_PASS);
// GA Data Feed query uri.
String baseUrl = "https://www.google.com/analytics/feeds/data";
DataQuery query = new DataQuery(baseUrl);
query.Ids = TABLE_ID;
query.Dimensions = "ga:source,ga:medium";
query.Metrics = "ga:visits,ga:bounces";
query.Segment = "gaid::-11";
query.Filters = "ga:medium==referral";
query.Sort = "-ga:visits";
query.NumberToRetrieve = 5;
query.GAStartDate = "2010-03-01";
query.GAEndDate = "2010-03-15";
Uri url = query.Uri;
Console.WriteLine("URL: " + url.ToString());
// Send our request to the Analytics API and wait for the results to
// come back.
feed = asv.Query(query);
}
refer also this guide to configure your project
Also follow this guide to use OAuth 2.0

WebConsumer.ProcessUserAuthorization returns null

I use DotNetOpenAuth.
So.. I am getting looking good response which has state Authenticated.
That is fine.
Now I want to get user profile info but always getting NULL.
Here is the code.
private ServiceProviderDescription GetServiceDescription()
{
string ValidateTokenEndPoint = ConfigurationManager.AppSettings["identityOAuthValidateTokenEndPointUrl"];
string ValidateAuthorizationHeaderEndPoint = ConfigurationManager.AppSettings["identityOAuthValidateAuthorizationHeaderEndPointUrl"];
string AccessTokenEndPoint = ConfigurationManager.AppSettings["identityOAuthAccessTokenURL"];
bool UseVersion10A = Convert.ToBoolean(ConfigurationManager.AppSettings["identityOAuthUseVersion10a"]);
string RequestTokenStr = ConfigurationManager.AppSettings["identityOAuthRequestTokenURL"];
string UserAuthStr = ConfigurationManager.AppSettings["identityOAuthAuthorizeUserURL"];
string AccessTokenStr = ConfigurationManager.AppSettings["identityOAuthAccessTokenURL"];
string InvalidateTokenStr = ConfigurationManager.AppSettings["identityOAuthRequestInvalidateTokenURL"];
return new ServiceProviderDescription
{
AccessTokenEndpoint = new MessageReceivingEndpoint(AccessTokenStr, HttpDeliveryMethods.PostRequest),
RequestTokenEndpoint = new MessageReceivingEndpoint(RequestTokenStr, HttpDeliveryMethods.PostRequest),
UserAuthorizationEndpoint = new MessageReceivingEndpoint(UserAuthStr, HttpDeliveryMethods.PostRequest),
TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
ProtocolVersion = DotNetOpenAuth.OAuth.ProtocolVersion.V10a
};
}
void GetUserProfile()
{
var tokenManager = TokenManagerFactory.GetTokenManager(TokenManagerType.InMemoryTokenManager);
tokenManager.ConsumerKey = ConfigurationManager.AppSettings["identityOAuthConsumerKey"];
tokenManager.ConsumerSecret = ConfigurationManager.AppSettings["identityOAuthConsumerSecret"];
var serviceDescription = GetServiceDescription();
var consumer = new WebConsumer(serviceDescription, tokenManager);
var result = consumer.ProcessUserAuthorization(response);
if (result != null) // It is always null
{
}
Well I checked 10 times and I am pretty sure that all URLs to create ServiceProviderDescription are correct.
Any clue?
Well
finally check your web.config app keys
add key="identityOAuthConsumerKey" value="put here correct data!!!"
add key="identityOAuthConsumerSecret" value="put here correct data!!!"
and if you use hosts file you have to put correct sitename as well
127.0.0.1 site1.host1.com

Categories