Facebook Shared Link - Scrape blog page right after published - c#

I'm developing a blog website (using Umbraco) where it also can share its blog page to Facebook automatically after the page has been published. I have created a Facebook app and used Facebook SDK for .NET in order to that and it works but one small problem is that when the link is shared for the first time, it looks ugly. No image, no title and no description, just url. I have to publish the second time to get the proper link. Heres what I've done so far:-
Programmatically use the scrape API using Facebook SDK for .NET. I even tried to loop through the scrape API 10x to test if it work but doesn't.
Supply the necessary Open Graph Tag in the header of the shared page.
og:title
og:description
og:image
og:image:width
og:image:height
og:type
og:fb_id
og:site_name
I'm using Umbraco ContentService Events to invoke the Facebook API functions:-
public class PublishEventHandler : ApplicationEventHandler
{
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
ContentService.Published += ContentServicePublished;
}
private void ContentServicePublished(IPublishingStrategy sender, PublishEventArgs<IContent> args)
{
foreach (var node in args.PublishedEntities)
{
foreach (var item in node.Properties)
{
//check property alias and its value
if (item.Alias == "autoPost" && (int)item.Value == 1)
{
var fbClient = new FacebookAuthClient();
var pageToken = fbClient.GetPageToken();
var url = umbraco.library.NiceUrlWithDomain(node.Id);
fbClient.ScrapePage(url, pageToken);
fbClient.SharePostOnPage(url, pageToken);
}
}
}
}
}
Scrape API function:-
public void ScrapePage(string url, string pageToken)
{
var scrapeResult = new FacebookClient(pageToken)
{
Version = "v2.9"
};
var response = scrapeResult.Post(new { id = url, scrape = "true" });
LogHelper.Info(this.GetType(), "|SCRAPE| " + response.ToString());
}
Share API function:-
public void SharePostOnPage(string url, string pageToken)
{
if (pageToken != null)
{
var result = new FacebookClient(pageToken)
{
Version = "v2.9"
};
var response = result.Post("/" + AuthConfig.facebookPageId + "/feed", new { link = url, scrape = "true" });
LogHelper.Info(this.GetType(), "|SHARE| " + response.ToString());
}
}
One more thing I want to add is when I checked the response for the scrape in the log. I only get the id and url but when I used the Graph API Explorer in https://developers.facebook.com I got the whole information of the page (id,url,title,description,etc..) and yes I've been Googling and researching for a week now for this problem before deciding to post this.

Related

How can I login with OAuth2.0 in DevOps API in C#?

I tried many API Calls with Postman and It works fine but I only get it to work with PAT.
Below you can find my API Call with my PAT. How can I change it to OAuth2.0?
By the way, I'm using the DataVerse API with OAuth2.0 but rewrite doesnt work.
EDIT:
I used the OAuthWebSample but there is another Error:
When I click on "Authorize" it says "The resource you are looking for has been removed, had its name changed, or is temporarily unavailable."
What I need to do to get it to work is to copy the website-url given in the publish section in visual studio and switch it.
So I got PUBLISHEDNAME.azurewebsites.net instead of APPNAME.azurewebsites.net
When I'm switching the CallbackUrl in web.config to PUBLISHEDNAME.azurewebsites.net I'll get a 400.
How can I fix it?
private const string URL = "DEV LINK";
string testToken = "PAT";
public TextMesh APIText;
public TextMeshProUGUI Text;
// Start is called before the first frame update
void Start()
{
}
public void GenerateDevOps()
{
StartCoroutine(ProcessDevOps(URL));
}
public IEnumerator ProcessDevOps(string uri)
{
using (UnityWebRequest request = UnityWebRequest.Get(uri))
{
request.SetRequestHeader("Content-Type", "application/json");
request.SetRequestHeader("Authorization", "Basic" + " " + testToken);
yield return request.SendWebRequest();
if (request.isNetworkError)
{
Debug.Log(request.error);
}
else
{
Debug.Log(request.downloadHandler.text);
Text.text = request.downloadHandler.text;
/* var data = JsonConvert.DeserializeObject<Root>(request.downloadHandler.text);
var dataInhalt = data.value.ToArray();
Debug.Log(dataInhalt);
foreach (Value content in dataInhalt)
{
string name = content.firstname;
string lastname = content.lastname;
//textapi.text = name + " " + lastname;
names = names + name + lastname + Environment.NewLine;
}
APIHeader.text = URL;
m_Object.text = names;
*/
}
}
}
The 404 error code means that the resource doesn't exist, or the authenticated user doesn't have permission to see that it exists. So here are two troubleshooting advices:
Check your REST API using PAT to see whether the error is about the API.
Configure OAuth 2.0 exactly as this document. In particular, make sure you have configured permissions correctly, which means that you can use the access token to read data and send it back.

Programatically press a button in a website from an app in a phone

I am creating a UWP app using c#. The app is supposed to fetch information from a website and present it to the user. I've went through the DOM of the site and managed to download the HTML of the site. But some of the information is hidden and only appears when certain buttons or selections are made on the website. Is there a way that I can programmatically go into the site, make a selection, the download the new html?
2nd Question: The app should have an fb liveChat function linked an fb page. How do I link facebook liveChat into this app? I do not have an idea in my head on how to make this work. Thank you for you help.
Here is an example for Entering text in search box and Click search button in Bing
Use WebView to do all the work
WebView webView = new WebView();
Use InvokeScriptAsync method for WebView to use JS code
webView.InvokeScriptAsync("eval", new string[] {});
Get the HTML of the site using below code
public LoadURI()
{
webView.Navigate(new Uri("https://www.bing.com/"));
webView.NavigationCompleted += webView_NavigationCompletedAsync;
}
string siteHtML = null;
private async void webView_NavigationCompletedAsync(WebView sender, WebViewNavigationCompletedEventArgs args)
{
siteHtML = await webView.InvokeScriptAsync("eval", new string[] { "document.documentElement.outerHTML;" });
}
Enter text in search box using below code
private async void EnterTextAsync(string enterText)
{
var functionString = string.Format(#"document.getElementsByClassName('b_searchbox')[0].innerText = '{0}';", enterText);
await webView.InvokeScriptAsync("eval", new string[] { functionString });
}
Simulate click using below code
private async void SimulateClickAsync()
{
var functionString = string.Format(#"ddocument.getElementsByClassName('b_searchboxSubmit')[0].click();");
await webView.InvokeScriptAsync("eval", new string[] { functionString });
}
Get new site's HTML using Step 3
Here is a Sample app for LogIn to StackOverflow: StackOverFlow-LogIn

Login with twitter to get user profile asp.net

I have a web application in asp.net . I want to use login with twiiter to get get user info. I have followed all instructions mentioned in below article
http://www.aspsnippets.com/Articles/Login-with-Twitter-in-ASPNet-using-Twitter-Button.aspx
I am getting redirected to twitter app then after authentication I am being redirected to my localhost app. Then I have check user is authorized but when I try to get user details by method FetchProfile() I am getting error.
My code is as below :
First on button click
protected void LoginTwitter(object sender, EventArgs e)
{
if (!TwitterConnect.IsAuthorized)
{
TwitterConnect twitter = new TwitterConnect();
twitter.Authorize(Request.Url.AbsoluteUri.Split('?')[0]);
}
}
then after authenticating back from twitter . on page load of application
I have check url its
http://localhost:63977/Account/Login?oauth_token=K0mECAAAAAAAxRXEAAABV44xPgc&oauth_verifier=qYLFiOlFPx4gxEu6V4AmTJG2JNjJ3nV2
then code to check
protected void Page_Load(object sender, EventArgs e)
{
TwitterConnect.API_Key = HelperClasses.TwitterApiKey;
TwitterConnect.API_Secret = HelperClasses.TwitterApiSecret;
if (Request.QueryString["oauth_token"] != null)
{
//twiiter
if (TwitterConnect.IsAuthorized)
{
TwitterConnect twitter = new TwitterConnect();
//LoggedIn User Twitter Profile Details
DataTable twitterUserDataTable = twitter.FetchProfile(); // error here
}
}
}
Tweetinvi provides a sample project doing exactly what you want to do : https://github.com/linvi/tweetinvi/tree/master/Examplinvi.Web.
I have highlighted the lines you will be interested in :
https://github.com/linvi/tweetinvi/blob/master/Examplinvi.Web/Controllers/HomeController.cs#L14-L36
You can also find more about the Authentication in tweetinvi here : https://github.com/linvi/tweetinvi/wiki/Authentication.
Here is the snippet that you want to use of ASP.NET authentication :
private IAuthenticationContext _authenticationContext;
// Step 1 : Redirect user to go on Twitter.com to authenticate
public ActionResult TwitterAuth()
{
var appCreds = new ConsumerCredentials("CONSUMER_KEY", "CONSUMER_SECRET");
// Specify the url you want the user to be redirected to
var redirectURL = "http://" + Request.Url.Authority + "/Home/ValidateTwitterAuth";
_authenticationContext = AuthFlow.InitAuthentication(appCreds, redirectURL);
return new RedirectResult(authenticationContext.AuthorizationURL);
}
public ActionResult ValidateTwitterAuth()
{
// Get some information back from the URL
var verifierCode = Request.Params.Get("oauth_verifier");
// Create the user credentials
var userCreds = AuthFlow.CreateCredentialsFromVerifierCode(verifierCode, _authenticationContext);
// Do whatever you want with the user now!
ViewBag.User = Tweetinvi.User.GetAuthenticatedUser(userCreds);
return View();
}

.NET C# aWeber API

Using .NET c# I need to programmatically manage / add subscribers to my lists in aWeber using the API. The process that I am tasked with will be a Windows Service that runs x # of times a day and updates the subscribers at aWeber and the lists that they are in.
So .. all of my research using the aWeber API with .NET has shown me that a signon page at aWeber must be completed in order to receive the oauth_verifier back in the callback URL.
So in summary here are my questions:
Any recommendations on how to accomplish this task using an unattended service?
Has anyone does this?
Any help is greatly appreciated.
Thanks
Emma
1) How to use Aweber .NET SDK to connect with Aweber account [Regular Account - (i.e.) Not the developer's one].
Download .NET SDK for Aweber from https://aweber.codeplex.com/
Ans :- 1) Create a developer account - Visit https://labs.aweber.com/
2) As you have successfully created the account you would see ConsumerKey, ConsumerSecret, & an AppId in your Application.
3) Then for the fist time add the following code.
string ConsumerKey = ConfigurationManager.AppSettings["AWeberConsumerKey"];
string ConsumerSecret= ConfigurationManager.AppSettings["AWeberConsumerSecret"];
Aweber.API api = new Aweber.API(ConsumerKey, ConsumerSecret);
api.CallbackUrl = "http://" + Request.Url.Host + ":" + Request.Url.Port + "/Authorize/Index";
api.get_request_token();
Response.Cookies["oauth_token"].Value = api.OAuthToken;
Response.Cookies["oauth_token_secret"].Value = api.OAuthTokenSecret;
api.authorize();
**Now create An Authorize controller in case of MVC or Authorize.aspx**
string ConsumerKey = ConfigurationManager.AppSettings["AWeberConsumerKey"];
string ConsumerSecret= ConfigurationManager.AppSettings["AWeberConsumerSecret"];
API api = new API(ConsumerKey, ConsumerSecret);
api.OAuthVerifier = Request["oauth_verifier"];
Response.Cookies["access_token"].Value = api.get_access_token();
Account account = api.getAccount();
**Now you can apply your code to create, delete... subscribers to/from the list**
When you run this code first the authorize page will appear where you need to add your Aweber regular account credentials.
Once it's verified then you'll get access to the aweber's(Customer) account.
**But you would not like the authorize page appear always whenever you run your application so you can omit it by doing the following steps.**
1. Use the PHP script provided in http://stackoverflow.com/questions/15378034/how-to-create-an-app-in-aweber
2. Run the above PHP script & you'll get the pair of accesskey & accesssecret.Copy them to your C# code (these are the permanent keys).
3. Initialize the API with this code:
string ConsumerKey = ConfigurationManager.AppSettings["AWeberConsumerKey"];
string ConsumerSecret = ConfigurationManager.AppSettings["AWeberConsumerSecret"];
string accessKey = ConfigurationManager.AppSettings["accessKey"];
string accessSecret = ConfigurationManager.AppSettings["accessSecret"];
Aweber.API api = new Aweber.API(ConsumerKey, ConsumerSecret);
api.OAuthToken = accessKey;
api.OAuthTokenSecret = accessSecret;
Account account = api.getAccount();
**Now we'll code to create subscriber to a particular list**
int listid = int.Parse(ConfigurationManager.AppSettings["ListId"]);
foreach (List list in account.lists().entries)
{
if (list.id == listid) Your List's ID **(Mylist - xxxxxxx)**
{
foreach (Subscriber subscriber in list.subscribers().entries)
{
if (subscriber.email.Equals(objRegModel.EmailID))
{
flag = false;
break;
**Checks whether the similar subscriber exists on the list**
}
else
{
flag = true;
}
}
if (flag == true)
{
BaseCollection<Subscriber> target = list.subscribers();
SortedList<string, object> parameters = new SortedList<string, object>();
parameters.Add("email", objRegModel.EmailID);
parameters.Add("name", objRegModel.FirstName + " " + objRegModel.LastName);
Subscriber subscriber = target.create(parameters);
**This will add the subscriber to the specified list only if does not exist on that list.**
}
}
}
**To Delete a particluar subscriber from the list**
Apply the same logic till Account account = api.getAccount();
To get the EmailID,IP Address etc of the subscribers on the
list.Refer to this link https://labs.aweber.com/docs/permissions
int listid = int.Parse(ConfigurationManager.AppSettings["ListId"]);
foreach (List list in account.lists().entries)
{
if (list.id == listid)
{
foreach (Subscriber subscriber in list.subscribers().entries)
{
We Perform the check whether the email of the subscriber exists on the list or not & accordingly delete it from the list.
if (subscriber.email == eid && subscriber.status != "unconfirmed")
{
try
{
if (subscriber.delete())
{
//Response.Write("Subscriber Successfully Deleted");
}
}
catch (Exception ex)
{
}
}
}
}
}
}

Webform routing home page in a folder like mvc rather than root of site

I've got webform routing setup on my asp.net webforms 3.5sp1 project. I would like to have the files for the site in a directory called content including the home page as I would like to run multiple sites using the same system.
In MVC there is a blank default page and the home page is in a folder called home. I can't seem to replicate this behaviour using web form routing but would like to. The blank page is always hit first. the route handler is hit second - it recognises that the request is for the home page and sets up the routing page but is not used. the route handler code is simple:
public string VirtualPath { get; private set; }
public IHttpHandler GetHttpHandler(RequestContext
requestContext)
{
string file = requestContext.RouteData.GetRequiredString("File");
string id = requestContext.RouteData.GetRequiredString("Id");
string queryString = "?menuid=" + id;
VirtualPath = "~/" + file;
HttpContext.Current.RewritePath(
string.Concat(
VirtualPath,
queryString));
var page = BuildManager.CreateInstanceFromVirtualPath
(VirtualPath, typeof(Page)) as IHttpHandler;
return page;
}
Is there anyway I can do this?
Update
Here is my global.asax route code:
public static void RegisterRoutes(RouteCollection routes)
{
Domain.RepositoryFactory repo = new RepositoryFactory();
foreach (var x in repo.MenuRepository.GetAllEnabledGetMenus())
{
if (string.IsNullOrEmpty(x.Url))
{
//add default
System.Web.Routing.RouteTable.Routes.Add(
new Route("Default.aspx",
new RouteValueDictionary(new { File = x.FileName,
Id = x.Id.ToString() }),
new CoreRouteHandler()));
}
else
{
string url = x.Url;
if(x.Url.StartsWith("/"))
{
url = url.Remove(0, 1);
}
System.Web.Routing.RouteTable.Routes.Add(
new System.Web.Routing.Route(url,
new RouteValueDictionary(new {File = x.FileName,
Id = x.Id.ToString()}),
new CoreRouteHandler()));
}
}
}
In my project I was needed to redirect all calls like www.site.com/MyPage to /Pages/MyPage.aspx. Was done by using HttpModule. Sample code below:
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication;
if (app.Context == null || app.Context.Response == null)
return;
String sourceUrl = String.Empty;
try
{
sourceUrl = app.Request.FilePath.TrimStart('/').TrimEnd('/').ToLower();
if (global::MyProject.Global.UrlShortcuts.ContainsKey(sourceUrl))
{
String newUrl = global::MyProject.Global.UrlShortcuts[sourceUrl];
app.Context.RewritePath(newUrl, string.Empty, app.Request.QueryString.ToString(), false);
}
else
{
}
}
catch (Exception Ex)
{
// handle your exception here
}
}
The minor issue was with hoster's IIS as I was unable to configure it to process all requests using ASP.NET. So I had to come up with blank placeholder .aspx files for pages (e.g. www.site.com/MyPage/default.aspx) created dynamically at application startup if it's running under IIS.
String server = Context.Request.ServerVariables["SERVER_SOFTWARE"];
// IIS puts some stuff here, WebDev server leaves the field empty
ok I got it working bit of a doh! moment.
I found this link while googling:
http://blog.ysatech.com/post/2010/07/11/ASP-NET-4-URL-Routing-Default-Page.aspx
all I needed to do was leave the route blank and delete the default.aspx file from the root of the site.
I also copied in the default system.webserver bis from a new MVC project as i think what i had there wasn't right. I'm upgrading an old project and so think it wasn't configured 100%. specifically: was missing.

Categories

Resources