How to create enterprise in Android Management API without customer interaction for getting enterprise token? - asp.net-core-3.1

This is controller code. Here I have provide how I'm creating enterprise. But currently I'm unable to create enterprise without enterprise token. Which I'm getting from customer, when customer registering thyself on play.google.com.
<!-- begin snippet: js hide: false console: true babel: false -->
using Google.Apis.Auth.AspNetCore3;
using Google.Apis.Auth.OAuth2;
using Google.Apis.AndroidManagement.v1;
using Google.Apis.Services;
using Microsoft.AspNetCore.Mvc;
using Google.Apis.AndroidManagement.v1.Data;
using System.Security.Claims;
using Newtonsoft.Json;
using QRCoder;
using System.Drawing;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using IHostingEnvironment = Microsoft.AspNetCore.Hosting.IHostingEnvironment;
namespace xProducts_RETL.Web.Controllers
{
public class EmmController : Controller
{
private readonly ILoggerManager _loggerManager;
private readonly IEmmMapper _iEmmMapper;
private readonly IConfiguration _iConfiguration;
private SignInManager<IdentityUser> _signInManager;
private readonly RoleManager<IdentityRole> _roleManager;
private readonly IHostingEnvironment _environment;
private readonly UserManager<IdentityUser> _userManager;
//private static readonly string ProjectId = "xpdemo";
private static readonly string ProjectId = "xdemo";
private static readonly string PolicyId = Zoo_ManagedPolicy";
private static readonly string PolicyId2 = "Zoo_WorkPolicy";
private static readonly string PolicyId3 = "Zoo_ManagedPolicyx";
//private static readonly string COSU_APP_PACKAGE_NAME = "com.google.android.apps.work.clouddpc";
//private static readonly string TestEnterpriseName = "enterprises/xxxxj";
private static readonly string TestEnterpriseName = "enterprises/xxxx8";
private const string Package_Outlook = "com.microsoft.office.outlook";
public EmmController(ILoggerManager loggermanager, IEmmMapper iEmmMapper, IConfiguration iConfiguration, SignInManager<IdentityUser> signInManager, RoleManager<IdentityRole> roleManager, UserManager<IdentityUser> userManager,IHostingEnvironment environment)
{
_loggerManager = loggermanager;
_iEmmMapper = iEmmMapper;
_iConfiguration = iConfiguration;
_signInManager = signInManager;
_userManager = userManager;
_roleManager = roleManager;
_environment = environment;
}
[HttpGet]
public IActionResult CreateEnterprise(EnterpriseDto enterpriseDto, string x)
{
try
{
//bind dropdowns
enterpriseDto.EnterpriseList = _iEmmMapper.GetEnterpriseList();
enterpriseDto.CreatedEnterpriseList = _iEmmMapper.GetGooglePlaySignedupEnterpriseList();
//fetch superadmin info
var superadminData = _userManager.GetUsersInRoleAsync("SuperAdmin").Result;
var superadminId = superadminData[0].Id;
var enterpriseList = _iEmmMapper.GetEnterprises().Where(x => x.OwnerIdentityId == superadminId && x.EnrollmentToken != null && x.EnrollmentTokenWP != null).ToList();
foreach (var enterprise in enterpriseList)
{
enterpriseDto.EnterpriseId = enterprise.EnterpriseId;
}
//
return View(enterpriseDto);
}
catch (Exception ex)
{
_loggerManager.LogError($"Something went wrong inside CreateEnterprise get action: {ex.Message}");
return View(enterpriseDto);
}
}
[HttpPost]
public IActionResult CreateEnterprise(EnterpriseDto enterpriseObj)
{
//populate default dropdown values
EnterpriseDto enterpriseModel = new();
enterpriseModel.EnterpriseList = _iEmmMapper.GetEnterpriseList();
enterpriseModel.CreatedEnterpriseList = _iEmmMapper.GetEnterpriseList();
if (enterpriseObj.Id != 0 || enterpriseObj.Id2 != 0)
{
#region serviceAccountAuthenctiactionFlow
//read service a/c creds
ServiceAccountCredential? credential;
string fileName = "service_account_key.json";
string path = Path.Combine(this._environment.WebRootPath, "ZeroTouchCredJSON", fileName);
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
credential = GoogleCredential.FromStream(stream)
.CreateScoped("https://www.googleapis.com/auth/androidmanagement")
.UnderlyingCredential as ServiceAccountCredential;
}
// Create a zero-touch enrollment API service endpoint.
var service = new AndroidManagementService(new BaseClientService.Initializer
{
HttpClientInitializer = credential,
ApplicationName = ResourceMsg.EMMAppName
});
#endregion
//create signup url
var signupData = service.SignupUrls.Create();
signupData.ProjectId = ProjectId;
signupData.CallbackUrl = _iConfiguration.GetValue<string>("AppSetting:CallBackURL");
var response = signupData.Execute();
if (response != null)
{
//create enterprise
var enterpriseData = service.Enterprises.Create(new Enterprise());
enterpriseData.ProjectId = ProjectId;
enterpriseData.SignupUrlName = response.Name;
enterpriseData.EnterpriseToken = "EAJmqckyhc_cep8KkQ-NDU3SG4uC7WfJk1oumRM9SqDPZ-jzMY6D-K-bbWaYHMDvMNsc-faLjwLdyF50yTZIKv_JK_vxEXxp2rPVKkDxzce8whACXz261yaM";
var enterpriseResponse = enterpriseData.Execute();
}
}
return View(enterpriseModel);
}
//[GoogleScopedAuthorize(AndroidManagementService.ScopeConstants.Androidmanagement)]
//[HttpPost]
//public async Task<IActionResult> CreateEnterprise([FromServices] IGoogleAuthProvider auth, EnterpriseDto enterpriseObj)
//{
// EnterpriseDto enterpriseModel = new();
// try
// {
// //bind dropdowns
// enterpriseModel.EnterpriseList = _iEmmMapper.GetEnterpriseList();
// enterpriseModel.CreatedEnterpriseList = _iEmmMapper.GetEnterpriseList();
// if (enterpriseObj.Id != 0 || enterpriseObj.Id2 != 0)
// {
// #region OAuthFlow
// // Check if the required scopes have been granted.
// if (await auth.RequireScopesAsync(AndroidManagementService.ScopeConstants.Androidmanagement) is IActionResult authResult)
// {
// return authResult;
// }
// //The required scopes have now been granted.
// GoogleCredential cred = await auth.GetCredentialAsync();
// var service = new AndroidManagementService(new BaseClientService.Initializer
// {
// HttpClientInitializer = cred.CreateScoped(AndroidManagementService.Scope.Androidmanagement),
// ApplicationName = ResourceMsg.EMMAppName
// });
// //Fetch client information from GCP
// dynamic name = "";
// dynamic email = "";
// if (User.Identity is ClaimsIdentity claimsIdentity)
// {
// var listk = claimsIdentity.Claims.Select(x => new { x.Type, x.Value }).ToList();
// name = listk[3].Value;
// email = User.FindFirstValue(ClaimTypes.Email);
// }
// //noob | superadmin
// if (email != "xy#gmail.com")
// {
// TempData["VerificationFailed"] = "You have logged in with a customer account. Please login with owner account to continue.";
// return View();
// }
// //var enterpriseRes = _iEmmMapper.GetEnterprises().Where(x=> x.ClientEmail == email);
// //if(enterpriseRes!= null)
// //{
// // TempData["MsgSignupFailed"] = "There is already an Enterprise exist. Please try with a different mail to add a new Enterprise.";
// // return View(enterpriseModel);
// //}
// #endregion
// //check userId existance
// string ownerUserId = "";
// var users = _userManager.Users.ToList();
// foreach (var user in users)
// {
// if (user.Email == "xx#yopmail.com")
// {
// ownerUserId = user.Id;
// break;
// }
// }
// //Enterprise Signup
// if (enterpriseObj.Id != 0 && enterpriseObj.ActionFlag == "Signup")
// {
// //create signup url
// var signupData = service.SignupUrls.Create();
// signupData.AccessToken = cred.UnderlyingCredential.GetAccessTokenForRequestAsync().Result;
// signupData.ProjectId = ProjectId;
// signupData.CallbackUrl = _iConfiguration.GetValue<string>("AppSetting:CallBackURL");
// //signupData.Service.
// var response = signupData.Execute();
// var ownerGoogleAccountId = User.FindFirstValue(ClaimTypes.Email);
// if (ownerGoogleAccountId != null && ownerUserId != null)
// {
// //assign client info to model
// enterpriseObj.ClientName = name;
// enterpriseObj.ClientEmail = email;
// //assign signup data to vmodel
// enterpriseObj.SignupUrlName = response.Name;
// enterpriseObj.SignupUrlURL = response.Url;
// enterpriseObj.OwnerIdentityId = ownerUserId;
// enterpriseObj.OwnerGoogleAccountId = ownerGoogleAccountId;
// //insert data into database
// var result = _iEmmMapper.CreateUpdateEnterprise(enterpriseObj);
// if (result == 1)
// {
// TempData["MsgSignupUrl"] = "Signup URL for the enterprise generated successfully.";
// return View(enterpriseModel);
// }
// }
// TempData["VerificationFailed"] = "Please login with current account details.";
// return View(enterpriseModel);
// }
// //Create Enterprise
// if (enterpriseObj.Id2 != 0 && enterpriseObj.ActionFlag == "Enterprise")
// {
// var response = _iEmmMapper.GetEnterprises().Where(x => x.Id == enterpriseObj.Id2).FirstOrDefault();
// if (response != null)
// {
// var enterpriseData = service.Enterprises.Create(new Enterprise());
// enterpriseData.AccessToken = cred.UnderlyingCredential.GetAccessTokenForRequestAsync().Result;
// enterpriseData.ProjectId = ProjectId;
// enterpriseData.SignupUrlName = response.SignupUrlName;
// enterpriseData.EnterpriseToken = response.EnterpriseToken;
// //enterprise generated
// var enterpriseResponse = enterpriseData.Execute();
// enterpriseModel.EnterpriseNameAPIFormat = enterpriseResponse.Name;
// var EnterpriseNameResponse = enterpriseResponse.Name;
// //enterpriseModel.EnterpriseToken = enterpriseData.EnterpriseToken;
// //fetch enterprise from db
// //var resultEnterprise = _iEmmMapper.GetEnterprises();
// //if (resultEnterprise != null)
// //{
// // foreach (var enterprise in resultEnterprise)
// // {
// //if (enterprise.ClientEmail == email)
// //{
// //prepare commonpolicies obj
// CommonPoliciesDto commonPolicies = new();
// //initialize model to assign apps into it
// commonPolicies.ApplicationDtoList = new List<ApplicationsDto>();
// var appModel = new ApplicationsDto();
// //enterprise Id >noob
// string[] enterpriseFullId = enterpriseResponse.Name.Split('/');
// string enterpriseId = enterpriseFullId[1];
// //create two different new policies
// string[] enterpriseArr = response.EnterpriseNameRequested.Split(' ');
// string enterpriseFirstName = enterpriseArr[0];
// string ManagedProfilePolicyName = enterpriseFirstName + "_FMDefaultPolicy";
// string WorkProfilePolicyName = enterpriseFirstName + "_WPDefaultPolicy";
// //var IsPolicyIdExist = _iEmmMapper.GetDevices().Where(x => x.PolicyId == PolicyId3 && x.EnterpriseId == enterpriseId).Any();//noob
// //if (IsPolicyIdExist)
// //{
// // SetDefaultPoliciesForExistingPolicy(TestEnterpriseName, PolicyId3);
// //}
// //else
// //{
// // //if policyId not assigned previously with any token
// // GenereateEnrollmentTokenForNewPolicy(TestEnterpriseName, PolicyId3);
// //}
// var IsManagedPolicyIdExist = _iEmmMapper.GetCommonPolicies().Where(x => x.PolicyId == ManagedProfilePolicyName && x.EnterpriseId == enterpriseId).Any();//noob
// if (!IsManagedPolicyIdExist)
// {
// //if policyId not assigned previously with any token
// GenereateEnrollmentTokenForNewPolicy(EnterpriseNameResponse, ManagedProfilePolicyName, ResourceMsg.FullyManged);
// }
// var IsWorkPolicyIdExist = _iEmmMapper.GetCommonPolicies().Where(x => x.PolicyId == WorkProfilePolicyName && x.EnterpriseId == enterpriseId).Any();//noob
// if (!IsWorkPolicyIdExist)
// {
// //if policyId not assigned previously with any token
// GenereateEnrollmentTokenForNewPolicy(EnterpriseNameResponse, WorkProfilePolicyName, ResourceMsg.Work);
// }
// #region localFunctionToGenerateTokenThruEnterpriseIdAndPolicyId
// void GenereateEnrollmentTokenForNewPolicy(string enterpriseNameAPIFormat, string myPolicyId, string policyProfileType)
// {
// //forming policy name
// string policyName = enterpriseNameAPIFormat + ResourceMsg.POLICIES_FORMAT + myPolicyId;
// //set a default hardware policy to newly registered device
// var appliedPolicyData = service.Enterprises.Policies.Patch(DefaultHardwarePolicies(myPolicyId), policyName).Execute();
// if (appliedPolicyData != null)//noob
// {
// enterpriseModel.PolicyName = policyName;
// //Create Default Policy in Database
// CommonPoliciesDto commonPoliciesModel = new()
// {
// UserIdentityId = ownerUserId,
// EnterpriseId = enterpriseId,
// PolicyId = myPolicyId,
// PolicyName = policyName,
// PolicyType = "Default",
// PolicyProfileType = policyProfileType,
// PolicyNameApiFormat = policyName,
// //
// MaximumTimeToLock = 0,
// StatusBarDisabled = false,
// KeyguardDisabled = false,
// WifiConfigDisabled = false,
// MobileNetworksConfigDisabled = false,
// BluetoothDisabled = true,
// BluetoothContactSharingDisabled = true,
// UsbFileTransferDisabled = true,
// AdjustVolumeDisabled = true,
// ScreenCaptureDisabled = true,
// ShareLocationDisabled = true,
// AutoDateAndTimeZone = ResourceMsg.AUTO_DATEANDTIMEZONE_UNSPECIFIED,
// CameraDisabled = true
// };
// var result = _iEmmMapper.CreateUpdateCommonPolicies(commonPoliciesModel);
// if (result == 0)
// {
// //TempData["MsgCmnPolicies"] = ResourceMsg.PoliciesCreatedSuccessfully;
// }
// var rtrvPolicy6 = _iEmmMapper.GetCommonPolicies().ToList();
// var rtrvPolicy = _iEmmMapper.GetCommonPolicies().Where(x => x.PolicyId == myPolicyId).FirstOrDefault();
// if (rtrvPolicy != null)
// {
// if (rtrvPolicy.PolicyProfileType == ResourceMsg.FullyManged)
// {
// //create enrollmentToken for Fully Managed Device with a policy name & assign created user
// //removed to setup KIOSK mode -> .SetUser(user.AccountIdentifier)
// EnrollmentToken token = new DemoEnrollmentToken().SetPolicyName(myPolicyId).SetDuration(ResourceMsg.ThirtyDaysInSecond).SetAllowPersonalUsage(ResourceMsg.PERSONAL_USAGE_DISALLOWED);
// var tokenResponse = service.Enterprises.EnrollmentTokens.Create(token, enterpriseNameAPIFormat).Execute();
// var eToken = tokenResponse.Value;
// enterpriseModel.EnrollmentToken = eToken;
// }
// else
// {
// if (rtrvPolicy.PolicyProfileType == ResourceMsg.Work)
// {
// //User setup [can't be use in KIOSK mode setup or only work for work profile]
// var user = new User
// {
// AccountIdentifier = Guid.NewGuid().ToString()
// };
// //create enrollmentToken for work profile Device with a policy name & assign created user
// EnrollmentToken token2 = new DemoEnrollmentToken().SetPolicyName(myPolicyId).SetUser(user.AccountIdentifier).SetDuration(ResourceMsg.ThirtyDaysInSecond).SetAllowPersonalUsage(ResourceMsg.PERSONAL_USAGE_ALLOWED);
// var tokenResponse2 = service.Enterprises.EnrollmentTokens.Create(token2, enterpriseNameAPIFormat).Execute();
// var eToken2 = tokenResponse2.Value;
// enterpriseModel.EnrollmentTokenWP = eToken2;
// }
// }
// }
// else
// {
// _loggerManager.LogError($"There is an error occured in GenereateEnrollmentTokenForNewPolicy local function. {ResourceMsg.InvalidPolicy}");
// TempData["Failure"] = ResourceMsg.InvalidPolicy;
// }
// }
// }
// #endregion
// enterpriseModel.Id = enterpriseObj.Id2;
// enterpriseModel.EnterpriseId = enterpriseId;
// if (enterpriseModel.Id != 0 && enterpriseModel.EnterpriseId != null)
// {
// //update data into database
// var entResponse = _iEmmMapper.CreateUpdateEnterprise(enterpriseModel);
// if (entResponse == 1)
// {
// TempData["MsgEnterprise"] = ResourceMsg.EnterpriseCreatedSuccessfully;
// }
// }
// //}
// // }
// //}
// }
// else
// {
// TempData["Failure"] = ResourceMsg.ContactTechnicalTeam;
// }
// }
// }
// return View(enterpriseModel);
// }
// catch (Google.GoogleApiException gex)
// {
// string msgErr = "Error in " + this.GetType().ToString();
// _loggerManager.LogError($"{msgErr}{gex.Message}");
// TempData["Failure"] = ResourceMsg.ContactTechnicalTeam;
// return View(enterpriseModel);
// }
// catch (Exception ex)
// {
// string msgErr = "Error in " + this.GetType().ToString();
// _loggerManager.LogError($"{msgErr}{ex.Message}");
// TempData["Failure"] = ResourceMsg.ContactTechnicalTeam;
// return View(enterpriseModel);
// }
//}
I'm facing this issue from a long time. Please share your feedback and help on this. Any help is appreciable.

There are two ways to create an enterprise:
Customer-managed enterprise: This is the recommended way to create an enterprise. This is the one you are using in your code and it requires an enterprise token.
EMM-managed enterprise: This is not the preferred method to create an enterprise, but it is still possible to create and manage an EMM-managed enterprise using this method. EMM managed enterprises can be created programmatically without customer intervention.
This guide covers how to create EMM-managed enterprises. With this method, EMMs have full control over an enterprise’s lifecycle.
Note: In the future, it would not be possible to create any EMM-managed enterprises using the enterprises.create method.
I suggest reviewing the process of creating a Customer-managed Enterprise by having the Enterprise IT admin complete the sign-up flow, as this is the preferred method.

Related

opcua session was closed by client

I have written the attached OpcUaConnector class for opc-ua connection related activities.
But it is not handling session. For example:
In opc ua configuration disabled the endpoint
In kepserver configuration did runtime > reinitializing
The windows service is throwing:
Source : system.Reactive.Core
InnerException : The session was closed by client
and stopping the windows service, as this error goes unhandled.
Can some one suggest how to handle session in opc-ua?
public class OpcUaConnector
{
private static SimplerAES simplerAES = new SimplerAES();
private DataContainer dataCointainer = null;
private UaTcpSessionChannel channel;
private string opcServerName = string.Empty;
private string opcUserId = string.Empty;
private string opcPassword = string.Empty;
private static ILog LogOpcStore;
private static System.IDisposable token;
private static uint id;
public OpcConnector(ILog Log)
{
IntializeLogOpcStore(Log);
}
private static void IntializeLogOpcStore(ILog Log)
{
LogOpcStore = Log;
}
public async Task OpenOpcConnection()
{
try
{
if ((!string.IsNullOrEmpty(this.opcServerName) & (this.opcServerName != AppMain.MyAppSettings.OpcServer)) ||
(!string.IsNullOrEmpty(this.opcUserId) & (this.opcUserId != AppMain.MyAppSettings.OpcUserId)) ||
(!string.IsNullOrEmpty(this.opcPassword) & (this.opcPassword != AppMain.MyAppSettings.OpcPassword)))
{
await channel.CloseAsync();
this.opcServerName = AppMain.MyAppSettings.OpcServer;
this.opcUserId = AppMain.MyAppSettings.OpcUserId;
this.opcPassword = AppMain.MyAppSettings.OpcPassword;
}
if (channel==null || (channel != null && (channel.State == CommunicationState.Closed || channel.State == CommunicationState.Faulted)))
{
var appDescription = new ApplicationDescription()
{
ApplicationName = "MyAppName",
ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:MyAppName",
ApplicationType = ApplicationType.Client,
};
//application data won't be deleted when uninstall
var certificateStore = new DirectoryStore(
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), MyAppName", "pki"),
true, true
);
//if the Ethernet cable unplugs or the Wifi drops out,
//you have some timeouts that can keep the session open for a while.
//There is a SessionTimeout (default of 2 min).
this.channel = new UaTcpSessionChannel(
appDescription,
certificateStore,
SignInOpc,
AppMain.MyAppSettings.OpcServer,
null,
options: new UaTcpSessionChannelOptions { SessionTimeout = 120000 });
await channel.OpenAsync();
//LogOpcStore.Info(String.Format("Opc connection sucessful"));
}
this.opcServerName = AppMain.MyAppSettings.OpcServer;
this.opcUserId = AppMain.MyAppSettings.OpcUserId;
this.opcPassword = AppMain.MyAppSettings.OpcPassword;
}
catch (Exception ex)
{
ServiceException serviceException = new ServiceException(ex.HResult + " " + ex.Message, "C052");
throw serviceException;
}
}
private static async Task RecursivelyFindNode(UaTcpSessionChannel channel, NodeId nodeid)
{
BrowseRequest browseRequest = new BrowseRequest
{
NodesToBrowse = new BrowseDescription[] { new BrowseDescription { NodeId = nodeid, BrowseDirection = BrowseDirection.Forward, ReferenceTypeId = NodeId.Parse(ReferenceTypeIds.HierarchicalReferences), NodeClassMask = (uint)NodeClass.Variable | (uint)NodeClass.Object, IncludeSubtypes = true, ResultMask = (uint)BrowseResultMask.All } },
};
BrowseResponse browseResponse = await channel.BrowseAsync(browseRequest);
foreach (var rd1 in browseResponse.Results[0].References ?? new ReferenceDescription[0])
{
uint chid = AppMain.MyTagDatabase.GetClientHandleByTag(rd1.DisplayName.ToString());
if (chid > 0)
{
AppMain.MyTagDatabase.UpdateNodeByClientHandle(chid, rd1.NodeId.ToString());
}
await RecursivelyFindNode(channel, ExpandedNodeId.ToNodeId(rd1.NodeId, channel.NamespaceUris));
}
}
public async Task CreateSubscription(DataContainer dc)
{
double curReadingValue;
try
{
dataCointainer = dc;
await RecursivelyFindNode(channel, NodeId.Parse(ObjectIds.RootFolder));
if (AppMain.MyTagDatabase.GetCntTagsNotInOpcServer() == AppMain.MyTagDatabase.GetTagCount())
{
//no need to create subscription
return;
}
//subscription timeout that is the product of PublishingInterval * LifetimeCount:
var subscriptionRequest = new CreateSubscriptionRequest
{
RequestedPublishingInterval = 1000f,
RequestedMaxKeepAliveCount = 30,
RequestedLifetimeCount = 30 * 3,
PublishingEnabled = true,
};
var subscriptionResponse = await channel.CreateSubscriptionAsync(subscriptionRequest);
id = subscriptionResponse.SubscriptionId;
var itemsToCreate = new MonitoredItemCreateRequest[AppMain.MyTagDatabase.GetTagHavingNodeCount()];
int i = 0;
foreach (var item in AppMain.MyTagDatabase.GetMyTagDatabase())
{
var itemKey = item.Key;
var itemValue = item.Value;
itemsToCreate[i] = new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse(itemValue.NodeId), AttributeId = AttributeIds.Value }, MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = itemKey, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } };
i++;
}
var itemsRequest = new CreateMonitoredItemsRequest
{
SubscriptionId = id,
ItemsToCreate = itemsToCreate,
};
var itemsResponse = await channel.CreateMonitoredItemsAsync(itemsRequest);
token = channel.Where(pr => pr.SubscriptionId == id).Subscribe(pr =>
{
// loop thru all the data change notifications
// receiving data change notifications here
var dcns = pr.NotificationMessage.NotificationData.OfType<DataChangeNotification>();
foreach (var dcn in dcns)
{
foreach (var min in dcn.MonitoredItems)
{
MyTag MyTag = new MyTag();
bool hasValue = AppMain.MyTagDatabase.GetMyTag(min.ClientHandle, out MyTag);
if (hasValue)
{
if (double.TryParse(min.Value.Value.ToString(), out curReadingValue))
{
//LogOpcStore.Info(String.Format("ClientHandle : {0} TagName : {1} SourceTimestamp : {2} ServerTimeStamp : {3} curReadingValue : {4}", min.ClientHandle, MyTag.TagName, min.Value.SourceTimestamp, min.Value.ServerTimestamp, curReadingValue));
AddDataPointToContainer(1, MyTag.TagName, min.Value.SourceTimestamp, curReadingValue);
}
}
}
}
});
}
catch (Exception ex)
{
//If the interruption lasts longer than these timeouts then the SessionChannel and Subscriptions will need to be recreated.
channel = null;
FatalServiceException fatalserviceException = new FatalServiceException(ex.Message, "C052");
throw fatalserviceException;
}
}
public async Task DeleteSubscription()
{
try
{
var request = new DeleteSubscriptionsRequest
{
SubscriptionIds = new uint[] { id }
};
await channel.DeleteSubscriptionsAsync(request);
token.Dispose();
}
catch (Exception ex)
{
ServiceException serviceException = new ServiceException(ex.Message, "C052");
throw serviceException;
}
}
private static async Task<IUserIdentity> SignInOpc(EndpointDescription endpoint)
{
IUserIdentity userIdentity = null;
if (endpoint.UserIdentityTokens.Any(p => p.TokenType == UserTokenType.Anonymous))
{
userIdentity = new AnonymousIdentity();
}
else if (endpoint.UserIdentityTokens.Any(p => p.TokenType == UserTokenType.UserName))
{
var userName = AppMain.MyAppSettings.OpcUserId;
var password = simplerAES.Decrypt(AppMain.MyAppSettings.OpcPassword);
userIdentity = new UserNameIdentity(userName, password);
}
return userIdentity;
}
private void AddDataPointToContainer(int dataType, string source, DateTime SourceTimestampUTC, double value)
{
ConditionValue conditionValue = new ConditionValue();
long timestamp = AppMain.ServerSyncTimeStore.ConvertDateTimeToTimeStampUTC(SourceTimestampUTC);
conditionValue.dataType = dataType;
conditionValue.source = source;
conditionValue.timestamp = timestamp;
conditionValue.SourceTimestampUTC = SourceTimestampUTC;
conditionValue.LocalTime = SourceTimestampUTC.ToLocalTime();
conditionValue.value = value;
//LogOpcStore.Info(String.Format("TagName : {0} SourceTimestampUTC : {1} timestamp : {2} LocalTime : {3} curReadingValue : {4}", source, SourceTimestampUTC, timestamp, SourceTimestampUTC.ToLocalTime(), value));
dataCointainer.AddDataPoint(conditionValue);
}
}
I see you are using the project https://github.com/convertersystems/opc-ua-client.
When a server closes the session and socket (as happens when you reinitialize Kepware) the client receives immediate notification that causes the client channel to fault. A faulted channel cannot be reopened, it should be aborted and a new channel should be created.
I made this standalone test, to show that you may have to catch an exception and recreate the channel and subscription. The point of this test is to subscribe to the CurrentTime node and collect 60 datachanges. The test should last a minute. If you re-init the Kepware server in the middle of the test, the code catches the exception and recreates the channel and subscription.
[TestMethod]
public async Task OpcConnectorTest()
{
var count = 0;
UaTcpSessionChannel channel = null;
while (count < 60)
{
try
{
channel = new UaTcpSessionChannel(
this.localDescription,
this.certificateStore,
new AnonymousIdentity(),
EndpointUrl,
SecurityPolicyUris.None,
loggerFactory: this.loggerFactory);
await channel.OpenAsync();
// create the keep alive subscription.
var subscriptionRequest = new CreateSubscriptionRequest
{
RequestedPublishingInterval = 1000f,
RequestedMaxKeepAliveCount = 30,
RequestedLifetimeCount = 30 * 3,
PublishingEnabled = true,
};
var subscriptionResponse = await channel.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false);
var id = subscriptionResponse.SubscriptionId;
var token = channel.Where(pr => pr.SubscriptionId == id).Subscribe(pr =>
{
// loop thru all the data change notifications
var dcns = pr.NotificationMessage.NotificationData.OfType<DataChangeNotification>();
foreach (var dcn in dcns)
{
foreach (var min in dcn.MonitoredItems)
{
Console.WriteLine($"sub: {pr.SubscriptionId}; handle: {min.ClientHandle}; value: {min.Value}");
count++;
}
}
});
var itemsRequest = new CreateMonitoredItemsRequest
{
SubscriptionId = id,
ItemsToCreate = new MonitoredItemCreateRequest[]
{
new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("i=2258"), AttributeId = AttributeIds.Value }, MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 12345, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }
},
};
var itemsResponse = await channel.CreateMonitoredItemsAsync(itemsRequest);
while (channel.State == CommunicationState.Opened && count < 60)
{
await Task.Delay(1000);
}
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.GetType()}. {ex.Message}");
}
}
if (channel != null)
{
Console.WriteLine($"Closing session '{channel.SessionId}'.");
await channel.CloseAsync();
}
}
I know this is an old post, but I stumbled upon this problem as well. For those interested:
The problem is related to the subscription(s).
When the following code is run:
token = channel.Where(pr => pr.SubscriptionId == id).Subscribe(pr =>
{
// loop thru all the data change notifications
// receiving data change notifications here
var dcns = pr.NotificationMessage.NotificationData.OfType<DataChangeNotification>();
foreach (var dcn in dcns)
{
foreach (var min in dcn.MonitoredItems)
{
MyTag MyTag = new MyTag();
bool hasValue = AppMain.MyTagDatabase.GetMyTag(min.ClientHandle, out MyTag);
if (hasValue)
{
if (double.TryParse(min.Value.Value.ToString(), out curReadingValue))
{
//LogOpcStore.Info(String.Format("ClientHandle : {0} TagName : {1} SourceTimestamp : {2} ServerTimeStamp : {3} curReadingValue : {4}", min.ClientHandle, MyTag.TagName, min.Value.SourceTimestamp, min.Value.ServerTimestamp, curReadingValue));
AddDataPointToContainer(1, MyTag.TagName, min.Value.SourceTimestamp, curReadingValue);
}
}
}
}
});
Observable.subscribe() takes multiple arguments. You should include what to do in case of an error. For example:
token = channel.Where(pr => pr.SubscriptionId == id).Subscribe(
pr => { code to run normally... },
ex => { Log.Info(ex.Message); },
() => { }
);
See http://reactivex.io/documentation/operators/subscribe.html for more information.

Unable to get user hometown and location from Facebook graph API

I am trying to get user hometown and location using Facebook graph API for the logged-in user
Public permissions to fetch location and hometown is granted by the user.
Graph API version v2.8
/me?fields=name,picture,location,hometown
You need to ask for permissions: user_hometown and user_location. The hometown/location is not included in the public permissions.
You can also check the scope of your access token here
Here is how you can get the complete user profile using FB token:
I am assuming you have given permission before getting token from graph api explore which is:
https://developers.facebook.com/tools/explorer/
public Profile GetProfile(string facebookID)
{
var url = "?fields=first_name,last_name,name,age_range,birthday, education, gender, hometown, locale, location, third_party_id, timezone, email";
dynamic result = _facebookClient.Get(facebookID + url);
var profile = new Profile();
if (result != null)
{
string resultStringify = result.ToString();
var resultBlock = JObject.Parse(resultStringify);
//if (result.ToString().Contains("first_name")) {
// profile.First_Name = resultBlock["first_name"].ToString();
//}
profile.First_Name = resultStringify.ExtractIfValueIsAvailable("first_name", resultBlock);
//if (result.ToString().Contains("last_name")) {
// profile.Last_Name = resultBlock["last_name"].ToString();
//}
profile.Last_Name = resultStringify.ExtractIfValueIsAvailable("last_name", resultBlock);
//if (result.ToString().Contains("name")) {
// profile.Name = resultBlock["name"].ToString();
//}
profile.Name = resultStringify.ExtractIfValueIsAvailable("name", resultBlock);
if (result.ToString().Contains("age_range"))
{
if (result.age_range.min != null) profile.Age_Range_Min = result.age_range.min;
if (result.age_range.max != null) profile.Age_Range_Max = result.age_range.max;
}
//if (result.ToString().Contains("birthday")) {
// profile.Birthday = DateTime.ParseExact(result.birthday, "MM/dd/yyyy", CultureInfo.InvariantCulture);
//}
profile.Birthday = resultStringify.ExtractIfDateTime("birthday", resultBlock);
//if (result.ToString().Contains("gender")) {
// profile.Gender = resultBlock["gender"].ToString();
//}
profile.Gender = resultStringify.ExtractIfValueIsAvailable("gender", resultBlock);
//if (result.ToString().Contains("hometown")) {
// profile.Hometown = resultBlock["hometown"]["name"].ToString();
//}
profile.Hometown = resultStringify.ExtractIfNameValueIsAvailable("hometown", resultBlock);
//if (result.ToString().Contains("locale")) {
// profile.Locale = resultBlock["locale"].ToString();
//}
profile.Locale = resultStringify.ExtractIfValueIsAvailable("locale", resultBlock);
//if (result.ToString().Contains("location")) {
// profile.Location = resultBlock["location"]["name"].ToString();
//}
profile.Location = resultStringify.ExtractIfNameValueIsAvailable("location", resultBlock);
//if (result.ToString().Contains("third_party_id")) {
// profile.Third_Party_ID = resultBlock["third_party_id"].ToString();
//}
profile.Third_Party_ID = resultStringify.ExtractIfValueIsAvailable("third_party_id", resultBlock);
profile.Timezone = resultStringify.ExtractIfValueIsAvailable("timezone", resultBlock);
profile.EMail = resultStringify.ExtractIfValueIsAvailable("email", resultBlock);
}
return profile;
}
public static string ExtractIfValueIsAvailable(this string result, string fieldName, dynamic resultBlock) => result.Contains(fieldName) ? resultBlock[fieldName].ToString() : string.Empty;
Hope it helps.

ASP MVC RouteConfig with authentication return error repository not found

I tried to make an authorization in my asp with my git client, so my git client will be requested an authorization from my server. When i tried to send a request to my git client, it was showing an error
repository http://localhost/git/user/try.git/info/ref not found
Here is my routeconfig
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
#region remoteURL
routes.MapRoute(
name: "RemoteURL",
url: "git/{project}.git/{*verb}",
defaults: new { controller = "Git", action = "Smart" }
);
routes.MapRoute(
name: "Git",
url: "git/{project}/{*verb}",
defaults: new { controller = "Git", action = "Smart" }
);
#endregion
#region Account;
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
#endregion;
}
and this is my controller that use an attribute :
public class GitController : Controller
{
[SmartGit]
public ActionResult Smart(string project, string service, string verb)
{
switch (verb)
{
case "info/refs":
return InfoRefs(project, service);
case "git-upload-pack":
return ExecutePack(project, "git-upload-pack");
case "git-receive-pack":
return ExecutePack(project, "git-receive-pack");
default:
return RedirectToAction("Tree", "Repository", new { Name = project });
}
}
and then this is my attribute smartgit
public class SmartGitAttribute : SmartAuthorizeAttribute
{
private const string AuthKey = "GitCodeGitAuthorize";
private GitCodeContext db = new GitCodeContext();
private string project;
private string verb;
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
var right = false;
var userfound = false;
List<string> paramParsing = new List<string>();
//url.Split("")
//base.OnAuthorization(filterContext);
var controller = filterContext.Controller as GitController;
if (controller == null)
return;
// git.exe not accept cookies as well as no session available
var auth = controller.HttpContext.Request.Headers["Authorization"];
if (!String.IsNullOrEmpty(auth))
{
var bytes = Convert.FromBase64String(auth.Substring(6));
var certificate = Encoding.ASCII.GetString(bytes);
var index = certificate.IndexOf(':');
var password = certificate.Substring(index + 1);
var username = certificate.Substring(0, index);
//var user = controller.MembershipService.Login(username, password);
if (WebSecurity.Login(username, password))
{
WebSecurity.Login(username, password);
userfound = true;
}
}
var projectField = controller.ValueProvider.GetValue("project");
var serviceField = controller.ValueProvider.GetValue("service");
var verbField = controller.ValueProvider.GetValue("service");
//filterContext.Controller.ValueProvider
var project = projectField == null ? null : projectField.AttemptedValue;
var service = serviceField == null ? null : serviceField.AttemptedValue;
var verb = verbField == null ? null : serviceField.AttemptedValue;
if (string.IsNullOrEmpty(service) && userfound) // redirect to git browser
{
right = true;
}
else if (string.Equals(service, "git-receive-pack", StringComparison.OrdinalIgnoreCase) && userfound) // git push
{
//right = controller.RepositoryService.CanWriteRepository(project, username);
right = true;
}
else if (string.Equals(service, "git-upload-pack", StringComparison.OrdinalIgnoreCase) && userfound ) // git fetch
{
//right = controller.RepositoryService.CanReadRepository(project, username);
right = true;
}
if (!userfound)
{
if (WebSecurity.CurrentUserName == "")
{
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.AddHeader("WWW-Authenticate", "Basic realm=\"coba\"");
filterContext.Result = new HttpUnauthorizedResult();
}
else
{
throw new UnauthorizedAccessException();
}
}
}
I found my own mistake, maybe my response doesn't have enough information so i decide to add a few information in my SmartGitAttribute
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.StatusDescription = "Unauthorized";
filterContext.HttpContext.Response.AddHeader("WWW-Authenticate", "Basic realm=\"Secure Area\"");
filterContext.HttpContext.Response.Write("401, please authenticate");
filterContext.HttpContext.Response.StatusCode = 401;
filterContext.Result = new EmptyResult();
filterContext.HttpContext.Response.End();
this is reference that can help you to solve response authentication

Entity Framework - how to save entity without saving related objects

In my Entity Framework, I have three related entities 'Client', 'ClientAddress' and 'LookupAddressType'. "LookupAddressType" is a master class specifying the type of available address type, like business address, residential address etc. ClientAddress depend on LookupAddresstype and Client. While saving a Client entity with relevant ClientAddress data, i'm getting following error.
"Violation of PRIMARY KEY constraint 'PK_LookupAddressType'. Cannot
insert duplicate key in object 'dbo.LookupAddressType'. The statement
has been terminated.
I do not need LookupAddressType to be inserted. Here I just need the relevant lookupAddressTypeId to be inserted in clientAddress entity.
The Saving code is like this:
Add(Client);
_objectContext.SaveChanges();
how can i do this?
The Load Code is below:
private void LoadClientDetails(EFEntities.Client _Client)
{
EFEntities.LookupClientStatu clientStatus;
var clientAddressList = new List<ClientAddress>();
if (_Client == null)
{
return;
}
//Assign data to client object
_Client.ClientName = rtxtName.Text;
_Client.Alias = rtxtAlias.Text;
_Client.ClientCode =Int32.Parse(rtxtClientCode.Text);
_Client.TaxPayerID = rtxtTaxPayerId.Text;
if (rcboStatus.SelectedIndex != 0)
{
clientStatus = new EFEntities.LookupClientStatu
{
ClientStatusID = (Guid) (rcboStatus.SelectedValue),
ClientStatusDescription = rcboStatus.Text
};
_Client.LookupClientStatu = clientStatus;
}
//_Client.Modified = EnvironmentClass.ModifiedUserInstance.Id;
_Client.EffectiveDate = rdtEffectiveDate.Value;
if (rdtExpDate.Value != rdtExpDate.MinDate)
{
_Client.ExpirationDate = rdtExpDate.Value;
}
else
{
_Client.ExpirationDate = null;
}
_Client.StartDate = DateTime.Now;
EFEntities.ClientAddress clientAddress = null;
// Iesi.Collections.Generic.ISet<ClientAddress> clientAddress = new HashedSet<ClientAddress>();
foreach (var cAddress in _clientController.client.ClientAddresses)
{
clientAddress = cAddress;
break;
}
if (clientAddress == null)
{
clientAddress = new EFEntities.ClientAddress();
}
clientAddress.Address1 = rtxtClientAdd1.Text;
clientAddress.Address2 = rtxtClientAdd2.Text;
clientAddress.Address3 = rtxtClientAdd3.Text;
// Address type details
if (rcboClientAddType.SelectedIndex != -1)
{
clientAddress.LookupAddressType = new EFEntities.LookupAddressType
{
AddressTypeID = (Guid) (rcboClientAddType.SelectedValue),
AddressTypeDescription = rcboClientAddType.Text
};
//clientAddress.AddressType.Id = Convert.ToByte(rcboClientAddType.SelectedValue);
}
clientAddress.City = rtxtClientCity.Text;
clientAddress.Client = _Client;
\
_Client.ClientAddresses.Add(clientAddress);
}
Well I did this to the following lines of code to make it work.
if (rcboClientAddType.SelectedIndex != -1)
{
clientAddress.LookupAddressType = new EFEntities.LookupAddressType
{
AddressTypeID = (Guid) (rcboClientAddType.SelectedValue),
AddressTypeDescription = rcboClientAddType.Text
};
//clientAddress.AddressType.Id = Convert.ToByte(rcboClientAddType.SelectedValue);
}
I changed the above code into this
if (rcboClientAddType.SelectedIndex != -1)
{
//clientAddress.LookupAddressType = new EFEntities.LookupAddressType
// {
// AddressTypeID = (Guid) (rcboClientAddType.SelectedValue),
// AddressTypeDescription = rcboClientAddType.Text
// };
clientAddress.AddressTypeID = (Guid)(rcboClientAddType.SelectedValue);
}

Entity Framework overwrites data when 2 two people save data simultaneously

In a function I pass a list of related values and loop over them to save changes in the database. All works well until 2 or more people use the same page to update different entities .Then only that data gets saved for which the changes were made more recently.
public bool UpdatePermanentDifferenceBL(List<PermanentDifferenceProperties> permDiffDetails)
{
try
{
int permanentDifferenceID=0;
int taxEntityID = 0;
int mapid = 0;
//using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
//{
Topaz.DAL.PermanentDifference permDiff;
for (int i = 0; i < permDiffDetails.Count; i++)
{
if ((bool)(HttpContext.Current.Session[GlobalConstant.currentDataSet]) == true && (int)(HttpContext.Current.Session[GlobalConstant.snapShotID]) == 0)
{
using (var ctx = new TopazDbContainer())
{
try
{
permanentDifferenceID = permDiffDetails[i].PermanentDifferenceID;
taxEntityID = permDiffDetails[i].TaxEntityID;
mapid = permDiffDetails[i].MapID;
permDiff = new Topaz.DAL.PermanentDifference();
permDiff = ctx.PermanentDifference.Where(p => p.PermanentDifferenceID == permanentDifferenceID && p.TaxEntityID == taxEntityID && p.MapID == mapid).SingleOrDefault();
permDiff.Business = permDiffDetails[i].Business;
permDiff.Interest = permDiffDetails[i].Interest;
permDiff.Corporate = permDiffDetails[i].Corporate;
permDiff.UnallocatedTax = permDiffDetails[i].UnallocatedTax;
permDiff.Total = permDiffDetails[i].Total;
permDiff.ModifiedBy = permDiffDetails[i].ModifiedBy;
permDiff.ModifiedDate = DateTime.Now;
ctx.SaveChanges();
}
catch (System.Data.OptimisticConcurrencyException ex)
{
permanentDifferenceID = permDiffDetails[i].PermanentDifferenceID;
taxEntityID = permDiffDetails[i].TaxEntityID;
mapid = permDiffDetails[i].MapID;
permDiff = new Topaz.DAL.PermanentDifference();
ctx.Refresh(System.Data.Objects.RefreshMode.StoreWins, permDiff);
permDiff = ctx.PermanentDifference.Where(p => p.PermanentDifferenceID == permanentDifferenceID && p.TaxEntityID == taxEntityID && p.MapID == mapid).SingleOrDefault();
permDiff.Business = permDiffDetails[i].Business;
permDiff.Interest = permDiffDetails[i].Interest;
permDiff.Corporate = permDiffDetails[i].Corporate;
permDiff.UnallocatedTax = permDiffDetails[i].UnallocatedTax;
permDiff.Total = permDiffDetails[i].Total;
permDiff.ModifiedBy = permDiffDetails[i].ModifiedBy;
permDiff.ModifiedDate = DateTime.Now;
ctx.SaveChanges();
}
}
}
//ctx.ContextOptions.UseLegacyPreserveChangesBehavior = true;
}
//}
//using (UnitOfWork uow = new UnitOfWork())
//{
// for (int i = 0; i < permDiffDetails.Count; i++)
// {
// if ((bool)(HttpContext.Current.Session[GlobalConstant.currentDataSet]) == true && (int)(HttpContext.Current.Session[GlobalConstant.snapShotID]) == 0)
// {
// Repository.PermanentDifferenceRepository pDiffRepo = new Repository.PermanentDifferenceRepository(uow);
// Topaz.DAL.PermanentDifference permDiff = pDiffRepo.GetByEntityId(permDiffDetails[i].PermanentDifferenceID, permDiffDetails[i].TaxEntityID, permDiffDetails[i].MapID);
// permDiff.Business = permDiffDetails[i].Business;
// permDiff.Interest = permDiffDetails[i].Interest;
// permDiff.Corporate = permDiffDetails[i].Corporate;
// permDiff.UnallocatedTax = permDiffDetails[i].UnallocatedTax;
// permDiff.Total = permDiffDetails[i].Total;
// permDiff.ModifiedBy = permDiffDetails[i].ModifiedBy;
// permDiff.ModifiedDate = DateTime.Now;
// pDiffRepo.ApplyChanges(permDiff);
// }
// else
// {
// int snapshotID = (int)(HttpContext.Current.Session[GlobalConstant.snapShotID]);
// SnapShotPermanentDifferenceRepository pDiffRepo = new SnapShotPermanentDifferenceRepository(uow);
// SnapShotPermanentDifference permDiff = pDiffRepo.GetByEntityId(permDiffDetails[i].PermanentDifferenceID, permDiffDetails[i].TaxEntityID, permDiffDetails[i].MapID,snapshotID);
// permDiff.SnapshotID = snapshotID;
// permDiff.Business = permDiffDetails[i].Business;
// permDiff.Interest = permDiffDetails[i].Interest;
// permDiff.Corporate = permDiffDetails[i].Corporate;
// permDiff.UnallocatedTax = permDiffDetails[i].UnallocatedTax;
// permDiff.Total = permDiffDetails[i].Total;
// permDiff.ModifiedBy = permDiffDetails[i].ModifiedBy;
// permDiff.ModifiedDate = DateTime.Now;
// pDiffRepo.ApplyChanges(permDiff);
// }
// }
// uow.SaveChanges();
return true;
}
catch (Exception ex)
{
TopazErrorLogs.AddTopazErrorLogBL(ex, 1, 1);
throw new TopazCustomException(GlobalConstant.errorMessage);
}
}
Any urgent assistance is much appreciated.
The common way to solve this is adding additional column to every table where you want to handle concurrency. This column will have ROWVERSION or TIMESTAMP data type. Once you map tables in EDMX you will get a new computed property of type byte[] and set its Concurrency mode to fixed. This setting will force EF to add additional WHERE condition to every UPDATE or DELETE statement validating that row version is the same as it was when the record was loaded from the database. If the row version is not the same (another thread updated the record) the record from modification is not found and you will get exception.
Database will change the value every time you update the record automatically. You just need to ensure that your entity uses the value which was retrieved when the entity was loaded from the database.
Apologies all the viewstate and to some extent session was the culprit and not EntityFramework.