I am trying to connect to QuickBooks desktop from QuickBooks anywhere, however, I fail to see my QuickBooks Desktop instance, Joe's Test Company. I see my QuickBooks Online instance only.
I believe the issue is my URL:
https://qbo.intuit.com/qbo1/rest/user/v2/
What is the base URL for QuickBooks Desktop?
Here is my code:
public void GetAccessTokenAndSecret()
{
string oauth_callback_url = HttpContext.Current.Request.RawUrl;
oauth_callback_url = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) + oauth_callback_url;
string consumerKey = _qboSettings.ConsumerKey;
string consumerSecret = _qboSettings.ConsumerKeySecret;
var oauthLink = Constants.OauthEndPoints.IdFedOAuthBaseUrl;
IToken token = (IToken)HttpContext.Current.Session["requestToken"];
IOAuthSession session = CreateSession();
IToken requestToken = session.GetRequestToken();
HttpContext.Current.Session["requestToken"] = requestToken;
string RequestToken = requestToken.Token;
string TokenSecret = requestToken.TokenSecret;
oauthLink = Constants.OauthEndPoints.AuthorizeUrl + "?oauth_token=" + RequestToken + "&oauth_callback=" + UriUtility.UrlEncode(oauth_callback_url);
HttpContext.Current.Response.Redirect(oauthLink);
}
/// <summary>
/// Creates Session
/// </summary>
/// <returns>Returns OAuth Session</returns>
protected IOAuthSession CreateSession()
{
OAuthConsumerContext consumerContext = new OAuthConsumerContext
{
ConsumerKey = _qboSettings.ConsumerKey,
ConsumerSecret = _qboSettings.ConsumerKeySecret,
SignatureMethod = SignatureMethod.HmacSha1
};
return new OAuthSession(consumerContext,
Constants.OauthEndPoints.IdFedOAuthBaseUrl + Constants.OauthEndPoints.UrlRequestToken,
Constants.OauthEndPoints.IdFedOAuthBaseUrl,
Constants.OauthEndPoints.IdFedOAuthBaseUrl + Constants.OauthEndPoints.UrlAccessToken);
}
Here are my constants:
using System.Globalization;
namespace HelloIntuitAnywhere.Utilities
{
using System.Configuration;
using System.Web;
/// <summary>
/// Contains Constants.
/// </summary>
internal class Constants
{
static string Url_Request_Token = "/get_request_token";
static string Url_Access_Token = "/get_access_token";
static string Intuit_OAuth_BaseUrl ="https://oauth.intuit.com/oauth/v1";
static string Intuit_Workplace_AuthorizeUrl = "https://workplace.intuit.com/Connect/Begin";
static string BlueDot_AppMenuUrl = "https://workplace.intuit.com/api/v1/Account/AppMenu";
static string DisconnectUr = "https://appcenter.intuit.com/api/v1/Connection/Disconnect";
static string oauth_callback_url = HttpContext.Current.Request.RawUrl.Replace("Configure", "OAuthHandler");
static string menuProxy = "MenuProxy.aspx";
static string grantUrl = "OauthGrant.aspx";
static string qbo_base_url = "https://qbo.intuit.com/qbo1/rest/user/v2/";
static string openid_identifier = "https://openid.intuit.com/Identity-YourAppName";
/// <summary>
/// OAuth EndPoints.
/// </summary>
internal class OauthEndPoints
{
/// <summary>
/// Url Request Token
/// </summary>
internal static string UrlRequestToken = Url_Request_Token != null ?
Url_Request_Token.ToString(CultureInfo.InvariantCulture) : "/get_request_token";
/// <summary>
/// Url Access Token
/// </summary>
internal static string UrlAccessToken = Url_Access_Token != null ?
Url_Access_Token.ToString(CultureInfo.InvariantCulture) : "/get_access_token";
/// <summary>
/// Federation base url.
/// </summary>
internal static string IdFedOAuthBaseUrl = Intuit_OAuth_BaseUrl != null ?
Intuit_OAuth_BaseUrl.ToString(CultureInfo.InvariantCulture) : "https://oauth.intuit.com/oauth/v1";
/// <summary>
/// Authorize url.
/// </summary>
internal static string AuthorizeUrl = Intuit_Workplace_AuthorizeUrl != null ?
Intuit_Workplace_AuthorizeUrl.ToString(CultureInfo.InvariantCulture) : "https://workplace.intuit.com/Connect/Begin";
}
/// <summary>
/// Intuit Anywhere Endpoints.
/// </summary>
internal class IaEndPoints
{
/// <summary>
/// BlueDot Menu Url.
/// </summary>
internal static string BlueDotAppMenuUrl = BlueDot_AppMenuUrl != null ?
BlueDot_AppMenuUrl.ToString(CultureInfo.InvariantCulture) : "https://workplace.intuit.com/api/v1/Account/AppMenu";
/// <summary>
/// Disconnect url.
/// </summary>
internal static string DisconnectUrl = DisconnectUrl != null ?
DisconnectUrl.ToString(CultureInfo.InvariantCulture) : "https://appcenter.intuit.com/api/v1/Connection/Disconnect";
}
}
}
What is the base URL for QuickBooks Desktop?
Per the documentation, the URLs for IDS for QuickBooks desktop follow the format:
https://services.intuit.com/sb/<objectName>/v2/<realmID>
However, the problem you're having:
I see my QuickBooks Online instance only.
Doesn't really sound base URL related. It sounds more like you haven't set up Sync Manager, or that your app settings don't have the QuickBooks desktop options ticked off to allow desktop versions of QuickBooks to connect to your app.
Related
I haven't find so far any good and update script for manage the Microsoft Spatial Azure Anchors, could you please review this code and tell me more or less if i am in the right way or not ? Actually I am trying to minimize the code for having the pure functionality, but i am stack and i can't even find an understandable guideline
hope the code is readable and well documented.
thanks in advance.
Andrea
using Microsoft.Azure;
using Microsoft.Azure.SpatialAnchors;
using Microsoft.Azure.SpatialAnchors.Unity;
using Microsoft.MixedReality.OpenXR;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.XR.WSA;
using UnityEngine.XR.WSA.Input;
public class AnchorsManager : MonoBehaviour
{
/// <summary>
/// Input
/// </summary>
private GameObject localAnchor;
/// <summary>
/// AZURE settings AccountId
/// </summary>
private string AccountId = "00886172-b41a-....";
/// <summary>
/// AZURE settings AccountKey
/// </summary>
private string AccountKey = "09c3eddc-....";
/// <summary>
/// AZURE settings AccountDomain
/// </summary>
private string AccountDomain = "northeurope.mixedreality.azure.com";
/// <summary>
/// Azure session
/// </summary>
private CloudSpatialAnchorSession cloudSession;
/// <summary>
/// For Storing the object Ids
/// </summary>
private AnchorLocateCriteria criteria = new AnchorLocateCriteria();
protected List<string> anchorIdsToLocate = new List<string>();
void Start()
{
InitializeSession();
}
/// <summary>
/// Only when the user drag an object we can save the anchor with the latest position
/// </summary>
void onMouseObjectDown(GameObject prefab)
{
this.localAnchor = prefab;
this.cloudSession.Start();
}
/// <summary>
/// Inizialize the cloudSpatialAnchorSession.
/// </summary>
void InitializeSession()
{
try {
this.cloudSession = new CloudSpatialAnchorSession();
this.cloudSession.Configuration.AccountId = this.AccountId;
this.cloudSession.Configuration.AccountKey = this.AccountKey;
this.cloudSession.Configuration.AccountDomain = this.AccountDomain;
this.cloudSession.SessionUpdated += (sender, args) =>
{
if (args.Status.RecommendedForCreateProgress != 0)
{
this.CreateAnchor();
}
};
//WATCHERS
this.cloudSession.CreateWatcher(criteria);
this.cloudSession.AnchorLocated += (object sender, AnchorLocatedEventArgs args) =>
{
switch (args.Status)
{
case LocateAnchorStatus.Located:
CloudSpatialAnchor foundAnchor = args.Anchor;
Debug.Log("ASA Info: Anchor located! Identifier: " + args.Identifier);
break;
case LocateAnchorStatus.AlreadyTracked:
Debug.Log("This anchor has already been reported and is being tracked" + args.Identifier);
break;
case LocateAnchorStatus.NotLocated:
Debug.Log("ASA Info: Anchor not located. Identifier: " + args.Identifier);
break;
case LocateAnchorStatus.NotLocatedAnchorDoesNotExist:
Debug.LogError("ASA Error: Anchor not located does not exist. Identifier: " + args.Identifier);
break;
}
};
}
catch (Exception ex) {
Debug.LogError("Error on initialize the session: " + ex.Message);
}
}
/// <summary>
/// CreateAnchor
/// </summary>
async void CreateAnchor()
{
// Create Anchor in local;
localAnchor.AddComponent<CloudNativeAnchor>();
CloudNativeAnchor cloudNativeAnchor = localAnchor.GetComponent<CloudNativeAnchor>();
if (cloudNativeAnchor.CloudAnchor == null) { await cloudNativeAnchor.NativeToCloud(); }
// Add Anchor property;
CloudSpatialAnchor cloudAnchor = cloudNativeAnchor.CloudAnchor;
cloudAnchor.AppProperties[#"room"] = #"bagno";
cloudAnchor.AppProperties[#"product"] = #"saponetta";
cloudAnchor.Expiration = DateTimeOffset.Now.AddDays(7);
// Create Anchor
await cloudSession.CreateAnchorAsync(cloudAnchor);
Debug.Log("Cloud anchor created with ID = " + cloudAnchor.Identifier);
// Save Anchor ID
this.anchorIdsToLocate.Add(cloudAnchor.Identifier);
this.criteria.Identifiers = anchorIdsToLocate.ToArray();
Debug.Log("Anchor Id has been saved on the array");
}
}
In unity I keep on getting this error that keeps on bugging me, I tried to remove packages to leave one of these errors and it kept on going on and on, i am developing a game right now using unity engine and the errors are a big pain for me, this is the code that someone asked for, i dont really have much else to write other than this, stackoverlow isnt letting me just post it because its too short
using System;
using System.IO;
using UnityEngine;
namespace UnityEditor.SettingsManagement
{
/// <inheritdoc />
/// <summary>
/// A settings repository that stores data local to a Unity project.
/// </summary>
[Serializable]
public sealed class PackageSettingsRepository : ISettingsRepository
{
const string k_PackageSettingsDirectory = "ProjectSettings/Packages";
const bool k_PrettyPrintJson = true;
bool m_Initialized;
[SerializeField]
string m_Name;
[SerializeField]
string m_Path;
[SerializeField]
SettingsDictionary m_Dictionary = new SettingsDictionary();
/// <summary>
/// Constructor sets the serialized data path.
/// </summary>
/// <param name="package">
/// The package name.
/// </param>
/// <param name="name">
/// A name for this settings file. Settings are saved in `ProjectSettings/Packages/{package}/{name}.json`.
/// </param>
public PackageSettingsRepository(string package, string name)
{
m_Name = name;
m_Path = GetSettingsPath(package, name);
m_Initialized = false;
AssemblyReloadEvents.beforeAssemblyReload += Save;
EditorApplication.quitting += Save;
}
void Init()
{
if (m_Initialized)
return;
m_Initialized = true;
if (File.Exists(path))
{
m_Dictionary = null;
var json = File.ReadAllText(path);
EditorJsonUtility.FromJsonOverwrite(json, this);
if(m_Dictionary == null)
m_Dictionary = new SettingsDictionary();
}
}
/// <value>
/// This repository implementation is relevant to the Project scope.
/// </value>
/// <inheritdoc cref="ISettingsRepository.scope"/>
public SettingsScope scope
{
get { return SettingsScope.Project; }
}
/// <value>
/// The full path to the settings file.
/// This corresponds to `Unity Project/Project Settings/Packages/com.unity.package/name`.
/// </value>
/// <inheritdoc cref="ISettingsRepository.path"/>
public string path
{
get { return m_Path; }
}
/// <summary>
/// The name of this settings file.
/// </summary>
public string name
{
get { return m_Name; }
}
// Cannot call FindFromAssembly from a constructor or field initializer
// static string CreateSettingsPath(Assembly assembly, string name)
// {
// var info = PackageManager.PackageInfo.FindForAssembly(assembly);
// return string.Format("{0}/{1}/{2}.json", k_PackageSettingsDirectory, info.name, name);
// }
/// <summary>
/// Get a path for a settings file relative to the calling assembly package directory.
/// </summary>
/// <param name="packageName">The name of the package requesting this setting.</param>
/// <param name="name">An optional name for the settings file. Default is "Settings."</param>
/// <returns>A package-scoped path to the settings file within Project Settings.</returns>
public static string GetSettingsPath(string packageName, string name = "Settings")
{
return string.Format("{0}/{1}/{2}.json", k_PackageSettingsDirectory, packageName, name);
}
/// <summary>
/// Save all settings to their serialized state.
/// </summary>
/// <inheritdoc cref="ISettingsRepository.Save"/>
public void Save()
{
Init();
if (!File.Exists(path))
{
var directory = Path.GetDirectoryName(path);
Directory.CreateDirectory(directory);
}
#if UNITY_2019_3_OR_NEWER
if (!AssetDatabase.IsOpenForEdit(path))
{
if (!AssetDatabase.MakeEditable(path))
{
Debug.LogWarning($"Could not save package settings to {path}");
return;
}
}
#endif
try
{
File.WriteAllText(path, EditorJsonUtility.ToJson(this, k_PrettyPrintJson));
}
catch (UnauthorizedAccessException)
{
Debug.LogWarning($"Could not save package settings to {path}");
}
}
/// <summary>
/// Set a value for key of type T.
/// </summary>
/// <param name="key">The settings key.</param>
/// <param name="value">The value to set. Must be serializable.</param>
/// <typeparam name="T">Type of value.</typeparam>
/// <inheritdoc cref="ISettingsRepository.Set{T}"/>
public void Set<T>(string key, T value)
{
Init();
m_Dictionary.Set<T>(key, value);
}
/// <summary>
/// Get a value with key of type T, or return the fallback value if no matching key is found.
/// </summary>
/// <param name="key">The settings key.</param>
/// <param name="fallback">If no key with a value of type T is found, this value is returned.</param>
/// <typeparam name="T">Type of value to search for.</typeparam>
/// <inheritdoc cref="ISettingsRepository.Get{T}"/>
public T Get<T>(string key, T fallback = default(T))
{
Init();
return m_Dictionary.Get<T>(key, fallback);
}
/// <summary>
/// Does the repository contain a setting with key and type.
/// </summary>
/// <param name="key">The settings key.</param>
/// <typeparam name="T">The type of value to search for.</typeparam>
/// <returns>True if a setting matching both key and type is found, false if no entry is found.</returns>
/// <inheritdoc cref="ISettingsRepository.ContainsKey{T}"/>
public bool ContainsKey<T>(string key)
{
Init();
return m_Dictionary.ContainsKey<T>(key);
}
/// <summary>
/// Remove a key value pair from the settings repository.
/// </summary>
/// <param name="key"></param>
/// <typeparam name="T"></typeparam>
/// <inheritdoc cref="ISettingsRepository.Remove{T}"/>
public void Remove<T>(string key)
{
Init();
m_Dictionary.Remove<T>(key);
By the definition of 'RequestScriptReload' :
"The Unity Editor reloads script assemblies asynchronously on the next frame. This resets the state of all the scripts, but Unity does not compile any code that has changed since the previous compilation."
That means that your problem is probably with something that you changed.
You can try:
Going back to the last time everything wored and go on from there.
Closing all of you unity and scripting applications and opening it again.
Following is the code I am using:
namespace MySite.Api
{
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System;
using System.Net.Http.Headers;
using Microsoft.Extensions.Logging;
/// <summary>
/// API query execution helper
/// </summary>
public class ApiQuery : IApiQuery
{
/// <summary>
/// configuration reference
/// </summary>
private IConfiguration config;
private HmacAuthenticationUtils hmacUtils;
private readonly ILogger logger;
private static readonly HttpClient httpClient = new HttpClient();
private static readonly HttpClient httpClientHMAC = new HttpClient();
/// <summary>
/// Initializes a new instance of the <see cref="ApiQuery"/> class.
/// </summary>
/// <param name="inConfig">injected configuration</param>
public ApiQuery(IConfiguration inConfig, HmacAuthenticationUtils hmacUtils, ILoggerFactory loggerFactory)
{
this.config = inConfig;
this.hmacUtils = hmacUtils;
this.logger = loggerFactory.CreateLogger("perfLogger");
}
/// <summary>
/// HTTP verb post
/// </summary>
/// <param name="requestUrl">API url</param>
/// <param name="requestData">request data</param>
/// <returns>HTTP response message</returns>
public virtual async Task<string> Post(string requestUrl, object requestData, HttpClient client = null)
{
return await PostBypassCache(requestUrl, requestData, client);
}
/// <summary>
/// HTTP verb post, specifically to bypass cache
/// </summary>
/// <param name="requestUrl">API url</param>
/// <param name="requestData">request data</param>
/// <returns>HTTP response message</returns>
public async Task<string> PostBypassCache(string requestUrl, object requestData, HttpClient client = null)
{
DateTime perfStart = DateTime.Now;
string customerJson = string.Empty;
if (requestData is string)
{
customerJson = requestData.ToString();
}
else
{
customerJson = JsonConvert.SerializeObject(requestData);
}
////just some template output to test which I'm getting back.
string resultJson = "{ 'status':'No Content'}";
if (client == null)
{
client = httpClient;
}
var response = await httpClient.PostAsync(requestUrl, new StringContent(customerJson, Encoding.UTF8, "application/json"));
if (response.StatusCode == HttpStatusCode.OK)
{
resultJson = await response.Content.ReadAsStringAsync();
}
logger.LogInformation("response time: " + (DateTime.Now - perfStart).TotalMilliseconds + "ms. Resource:" + requestUrl);
return resultJson;
}
/// <summary>
/// HTTP verb post
/// </summary>
/// <param name="requestUrl">API url</param>
/// <param name="requestData">request data</param>
/// <param name="headerset">header data</param>
/// <returns>string data</returns>
public async Task<string> PostHmacAuth(string requestUrl, string requestData)
{
var httpRequest = new HttpRequestMessage(HttpMethod.Post, requestUrl);
httpRequest.Content = new StringContent(requestData, Encoding.UTF8, "application/json");
var signature = await Utils.GenerateAuthenticationString(httpRequest);
httpClientHMAC.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(HmacAuthenticationUtils.HmacHeader, signature);
return await PostBypassCache(requestUrl, requestData, httpClientHMAC);
}
}
}
In the Startup.cs, I inject it
services.AddTransient<IApiQuery, ApiQuery>();
I have recently made these changes as previously the code was actually instantiating the httpClient in each of the method, i.e.,
var client = new HttpClient();
At some places it was like:
using(var client = new HttpClient()){}
I Think due to such code, the the appPool is showing error due to which my IIS hangs, and the problem only get solved by restarting the appPool. I conclude this to be problem as I went through a lot of other articles. What I was not able to conclude is on if it should be a good idea to inject the ApiQuery Service as singleton itself.
Will it be better to inject it as ?
As I am injecting IApiQuery to every business service right now as a transient service, will it be good idea ? Any thoughts
HttpClient should be singleton-scoped. There's a finite number of connections available on your machine, and since HttpClient holds on to connections it creates, having multiple instances floating around can quickly exhaust your connection pool.
Beginning with ASP.NET Core 2.1, there exists IHttpClientFactory which provides a simple and reusable way of injecting properly scoped HttpClient instances. However, since you're using 1.1, that's not available to you. The recommended path would be to upgrade your project to 2.1. The 1.X line of ASP.NET Core is frankly trash. It wasn't ready for production use, despite being an official release.
If you insist on sticking with 1.1, then you'll need to implement your own method of reusing HttpClient instances. The most straightforward way is to use "accessor" classes, which you can then utilize to inject different HttpClients into different objects. For example:
public class ApiHttpClientAccessor : IDisposable
{
public ApiHttpClientAccessor()
{
HttpClient = new HttpClient
{
BaseAddress = new Uri("https://foo.com")
};
}
public HttpClient HttpClient { get; }
private bool _disposed;
public virtual void Dispose(bool disposing)
{
if (disposing && !_disposed)
{
HttpClient.Dispose();
}
_disposed = true;
}
public bool Dispose() =>
Dispose(true);
}
Then, you can register this accessor class as a singleton, meaning it will only be created once (so the contained HttpClient will also only be created once). Then, set up your class to accept this accessor in its constructor:
public class ApiQuery : IApiQuery
{
private readonly HttpClient _client;
public ApiQuery(ApiHttpClientAccessor httpClientAccessor)
{
_client = (httpClientAccessor ?? throw new ArgumentNullException(nameof(httpClientAccessor))).HttpClient;
}
...
}
And in Startup.cs:
services.AddSingleton<ApiHttpClientAccessor>();
services.AddTransient<IApiQuery, ApiQuery>();
thanks for taking a look at this. I'm new to Unity and struggling to understand how to fix this error.
Assets/Watson/Scripts/Logging/Logger.cs(115,53): error CS0311: The type IBM.Watson.DeveloperCloud.Logging.LogSystem' cannot be used as type parameter T in the generic type or method Singleton. There is no implicit reference conversion from IBM.Watson.DeveloperCloud.Logging.LogSystem' to `UnityEngine.MonoBehaviour
This is the line causing the error:
public static LogSystem Instance { get { return Singleton<LogSystem>.Instance; } }
And this is it in context:
/// <summary>
/// This singleton class maintains the of list of installed reactors and handles all LogRecord
/// objects. See the static class Log for functions the end user of this system should actually
/// be calling. This class is thread safe.
/// </summary>
public class LogSystem
{
#region Public Properties
/// <summary>
/// Returns the singleton instance of the Logger object.
/// </summary>
**public static LogSystem Instance { get { return Singleton<LogSystem>.Instance; } }**
#endregion
#region Private Data
private static bool sm_bInstalledDefaultReactors = false;
List<ILogReactor> m_Reactors = new List<ILogReactor>();
#endregion
#region Public Functions
public static List<ILogReactor> ReactorsInstalled
{
get
{
return LogSystem.Instance.m_Reactors;
}
}
/// <summary>
/// Install a default debug and file reactor.
/// </summary>
public static void InstallDefaultReactors(int logHistory = 2, LogLevel logLevelFileReactor = LogLevel.STATUS)
{
if (!sm_bInstalledDefaultReactors)
{
// install the default reactors...
sm_bInstalledDefaultReactors = true;
#if UNITY_EDITOR || UNITY_IOS || UNITY_ANDROID
LogSystem.Instance.InstallReactor(new DebugReactor());
#endif
if (!string.IsNullOrEmpty(Constants.Path.LOG_FOLDER) && !System.IO.Directory.Exists(Application.persistentDataPath + Constants.Path.LOG_FOLDER))
System.IO.Directory.CreateDirectory(Application.persistentDataPath + Constants.Path.LOG_FOLDER);
LogSystem.Instance.InstallReactor(new FileReactor(Application.persistentDataPath + Constants.Path.LOG_FOLDER + "/" + Application.productName + ".log", logLevelFileReactor, logHistory));
Application.logMessageReceived += UnityLogCallback;
}
}
static void UnityLogCallback(string condition, string stacktrace, LogType type)
{
if (type == LogType.Exception)
Log.Critical("Unity", "Unity Exception {0} : {1}", condition, stacktrace);
}
/// <summary>
/// Installs a reactor into this Logger.
/// </summary>
/// <param name="reactor">The reactor object.</param>
public void InstallReactor(ILogReactor reactor)
{
lock (m_Reactors)
{
m_Reactors.Add(reactor);
}
// set our default reactor flag to true if the user installs their own reactors.
sm_bInstalledDefaultReactors = true;
}
/// <summary>
/// Removes a reactor from this Logger.
/// </summary>
/// <param name="reactor">The reactor to remove.</param>
/// <returns>Returns true on success.</returns>
public bool RemoveReactor(ILogReactor reactor)
{
lock (m_Reactors)
{
return m_Reactors.Remove(reactor);
}
}
/// <summary>
/// Send the given LogRecord to all installed reactors.
/// </summary>
/// <param name="log">The LogRecord to pass to all reactors.</param>
public void ProcessLog(LogRecord log)
{
lock (m_Reactors)
{
foreach (var reactor in m_Reactors)
reactor.ProcessLog(log);
}
}
#endregion
}
public static LogSystem Instance
{
get
{
return instance;
}
}
private static LogSystem instance;
// Ctor of the class
public LogSystem()
{
if(instance == null) { instance = this;}
}
This is a very basic singleton pattern implementation. You can find more advanced ones online.
Well, I am a new guy who is trying to develop a web application whose user are will be authenticated through Facebook. I am developing the application in MVC 4 .Net Framework. As it's internal programs are already done so I need not to do much coding. I have just put the API ID and Secret Key in the scope
OAuthWebSecurity.RegisterFacebookClient(
appId: "750397051803327",
appSecret: "**************************");
And here is my Application http://imgur.com/a/k4Vd0
My Application is taking properly the user permission from the user perfectly. http://imgur.com/a/bqzj5 but after taking permission it is not providing the login state of the user by showing such exception http://imgur.com/a/h81Oh login failed. I debugged form the code end and I observed that it is sending isLoggedin as false http://imgur.com/a/UuLIe therefore my I am not getting the access.
However 2 days before I am not getting such exception. I was getting data simply fine. Here is a snapshot of my previous data. http://imgur.com/a/Bc49F
I need that data again, but how? Is there anything need to change in my application dashboard? Possibly I have changed something in application dashboard. if yes then what is particularly that?
Another things I'm confused that what is the need for PRODUCTS? Do I need anything from the products for this special reason to get the data. If yes then which one shall I need and how to configure it to get back my previous systematic process in which I was getting data smoothly.
If I add App Center from the PRODUCTS I am obtaining two other secret keys like Account Kit App Secret and Account Kit Client Token Is that I need to use these keys for my requested case. For such login approval specific which Products are need or nothing need at all from PRODUCTS. I am so confused about it how to configure an application.
Please suggest me how to solve this problem in addition how to configure my application API. Thank you.
According to Previous Answer I got my solution. In MVC4 everyone write down their AppID and SecurityCode. Due to change of facebook GRAPH API those previous links are broken. Consequently everyone need to change the RegisterFacebookClient calss. But this class is a sealed class in the .Net library, so anyone can't extend or overwrite it. As a result we need to use a wrapper class. Let us consider my Wrapper class is FacebookClientV2Dot3 therefore my class will be
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using DotNetOpenAuth.AspNet.Clients;
using Newtonsoft.Json;
public class FacebookClientV2Dot3 : OAuth2Client
{
#region Constants and Fields
/// <summary>
/// The authorization endpoint.
/// </summary>
private const string AuthorizationEndpoint = "https://www.facebook.com/dialog/oauth";
/// <summary>
/// The token endpoint.
/// </summary>
private const string TokenEndpoint = "https://graph.facebook.com/oauth/access_token";
/// <summary>
/// The user info endpoint.
/// </summary>
private const string UserInfoEndpoint = "https://graph.facebook.com/me";
/// <summary>
/// The app id.
/// </summary>
private readonly string _appId;
/// <summary>
/// The app secret.
/// </summary>
private readonly string _appSecret;
/// <summary>
/// The requested scopes.
/// </summary>
private readonly string[] _requestedScopes;
#endregion
/// <summary>
/// Creates a new Facebook OAuth2 client, requesting the default "email" scope.
/// </summary>
/// <param name="appId">The Facebook App Id</param>
/// <param name="appSecret">The Facebook App Secret</param>
public FacebookClient(string appId, string appSecret)
: this(appId, appSecret, new[] { "email" }) { }
/// <summary>
/// Creates a new Facebook OAuth2 client.
/// </summary>
/// <param name="appId">The Facebook App Id</param>
/// <param name="appSecret">The Facebook App Secret</param>
/// <param name="requestedScopes">One or more requested scopes, passed without the base URI.</param>
public FacebookClient(string appId, string appSecret, params string[] requestedScopes)
: base("facebook")
{
if (string.IsNullOrWhiteSpace(appId))
throw new ArgumentNullException("appId");
if (string.IsNullOrWhiteSpace(appSecret))
throw new ArgumentNullException("appSecret");
if (requestedScopes == null)
throw new ArgumentNullException("requestedScopes");
if (requestedScopes.Length == 0)
throw new ArgumentException("One or more scopes must be requested.", "requestedScopes");
_appId = appId;
_appSecret = appSecret;
_requestedScopes = requestedScopes;
}
protected override Uri GetServiceLoginUrl(Uri returnUrl)
{
var state = string.IsNullOrEmpty(returnUrl.Query) ? string.Empty : returnUrl.Query.Substring(1);
return BuildUri(AuthorizationEndpoint, new NameValueCollection
{
{ "client_id", _appId },
{ "scope", string.Join(" ", _requestedScopes) },
{ "redirect_uri", returnUrl.GetLeftPart(UriPartial.Path) },
{ "state", state },
});
}
protected override IDictionary<string, string> GetUserData(string accessToken)
{
var uri = BuildUri(UserInfoEndpoint, new NameValueCollection { { "access_token", accessToken } });
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
using (var webResponse = webRequest.GetResponse())
using (var stream = webResponse.GetResponseStream())
{
if (stream == null)
return null;
using (var textReader = new StreamReader(stream))
{
var json = textReader.ReadToEnd();
var extraData = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
var data = extraData.ToDictionary(x => x.Key, x => x.Value.ToString());
data.Add("picture", string.Format("https://graph.facebook.com/{0}/picture", data["id"]));
return data;
}
}
}
protected override string QueryAccessToken(Uri returnUrl, string authorizationCode)
{
var uri = BuildUri(TokenEndpoint, new NameValueCollection
{
{ "code", authorizationCode },
{ "client_id", _appId },
{ "client_secret", _appSecret },
{ "redirect_uri", returnUrl.GetLeftPart(UriPartial.Path) },
});
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
string accessToken = null;
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
// handle response from FB
// this will not be a url with params like the first request to get the 'code'
Encoding rEncoding = Encoding.GetEncoding(response.CharacterSet);
using (StreamReader sr = new StreamReader(response.GetResponseStream(), rEncoding))
{
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var jsonObject = serializer.DeserializeObject(sr.ReadToEnd());
var jConvert = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(jsonObject));
Dictionary<string, object> desirializedJsonObject = JsonConvert.DeserializeObject<Dictionary<string, object>>(jConvert.ToString());
accessToken = desirializedJsonObject["access_token"].ToString();
}
return accessToken;
}
private static Uri BuildUri(string baseUri, NameValueCollection queryParameters)
{
var keyValuePairs = queryParameters.AllKeys.Select(k => HttpUtility.UrlEncode(k) + "=" + HttpUtility.UrlEncode(queryParameters[k]));
var qs = String.Join("&", keyValuePairs);
var builder = new UriBuilder(baseUri) { Query = qs };
return builder.Uri;
}
/// <summary>
/// Facebook works best when return data be packed into a "state" parameter.
/// This should be called before verifying the request, so that the url is rewritten to support this.
/// </summary>
public static void RewriteRequest()
{
var ctx = HttpContext.Current;
var stateString = HttpUtility.UrlDecode(ctx.Request.QueryString["state"]);
if (stateString == null || !stateString.Contains("__provider__=facebook"))
return;
var q = HttpUtility.ParseQueryString(stateString);
q.Add(ctx.Request.QueryString);
q.Remove("state");
ctx.RewritePath(ctx.Request.Path + "?" + q);
}
}
Look here you I have replaces all the API links by newer version links.
Now you need to modify your
AuthConfig
Just use a wrapper class
OAuthWebSecurity.RegisterClient(new FacebookClientV2Dot3("AppID", "HassedPassword"));
Then all success. You facebook login will be back in previous state.
However you can face a new issue regarding this new API rather than previous API, the problem is that IP Whitelisting. Like this image. Hope you will need nothing but this. Happy coding.
Yes!!!!
I got the solution of my own problem. According to Facebook developers bug report all Facebook log is not working from 28th March 2017. They also let us know through their developers Facebook group. The post link is here.
According to one of the Developer teams had said we're finding that
facebook authentication just stopped working (2pm EST) across multiple
apps that we manage. apps haven't changed, apps haven't been
suspended..... not sure where to report this since "status" is all
good......