Can we run jquery spellchecker by badsyntax using asp.net web services? - jquery-plugins

I have been researching for quite a while now for an appropriate spell checker for textbox and multiline textbox.
I can see that this functionality is built in for firefox but its not present in chrome.
I was checking out all the demos for spellcheck which is provided by
jquery spellchecker - badsyntax and i find it really nice and useful.
here is the link
http://jquery-spellchecker.badsyntax.co/
But my problem here is- spellchecker makes use of php webservices and i want to use it in my ASP.net Webapplication.
is there any work around so that i can run it using asp.net web services?
Please provide me with a solution.

I'm the author of the plugin and would really like to incorporate some other webservice implementations.
This popped up recently in my google alerts, I can't verify it works though:
http://www.yodotnet.com/post/2013/02/24/Jquery-Spellchecker-for-NET.aspx
https://github.com/AnthonyTerra/ASP.MVC-Jquery-Spellchecker

Hi Guys: Veerendra Prabhu, badsyntax; I've integrated Nhunspell and asp.net Web Service (.asmx) and currently I'm trying to integrate jquery spellchecker - badsyntax to the proyect, I'm jquery spellchecker now conects with my web services but Im still dealing whith the returned data type of my web service to allow jquery spellcheker does its magic, but I thinks its something.
I took ideas from:
deepinthecode.com
Here are some ideas that I used:
I used NHusnpell that helps to get the incorrect words within a passed text and look into the dictionary (open office downloaded as .oxt but you have to chante to zip to get en_US.aff, and en_US.dic) this files needs to be at bin directory.
At Glabal.asax file I created a static instance of NHuspell that does all the work.
public class Global : System.Web.HttpApplication
{
static SpellEngine spellEngine;
static public SpellEngine SpellEngine { get { return spellEngine; } }
protected void Application_Start(object sender, EventArgs e)
{
try
{
string dictionaryPath = Server.MapPath("Bin") + "\\";
Hunspell.NativeDllPath = dictionaryPath;
spellEngine = new SpellEngine();
LanguageConfig enConfig = new LanguageConfig();
enConfig.LanguageCode = "en";
enConfig.HunspellAffFile = dictionaryPath + "en_us.aff";
enConfig.HunspellDictFile = dictionaryPath + "en_us.dic";
enConfig.HunspellKey = "";
//enConfig.HyphenDictFile = dictionaryPath + "hyph_en_us.dic";
spellEngine.AddLanguage(enConfig);
}
catch (Exception ex)
{
if (spellEngine != null)
spellEngine.Dispose();
}
}
...
protected void Application_End(object sender, EventArgs e)
{
if (spellEngine != null)
spellEngine.Dispose();
spellEngine = null;
}
}
Then I created an ASMX web service for the Get_Incorrect_Words and Get_Suggestions methods
/// <summary>
/// Summary description for SpellCheckerService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService()]
public class SpellCheckerService : System.Web.Services.WebService
{
[WebMethod]
//[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string get_incorrect_words(string words)
{
Dictionary<string, string> IncorrectWords = new Dictionary<string, string>();
List<string> wrongWords = new List<string>();
var palabras = words.Split(' ');
// Check spelling of each word that has been passed to the method
foreach (string word in palabras)
{
bool correct = Global.SpellEngine["en"].Spell(word);
if (!correct){
wrongWords.Add(word);
}
}
IncorrectWords.Add("data", wrongWords[0]);
return wrongWords[0];
}
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public List<string> get_suggestions(string word)
{
List<string> suggestions = new List<string>();
suggestions = Global.SpellEngine["en"].Suggest(word);
suggestions.Sort();
return suggestions;
}
And Finally I modified the calls to the get_incorrect_words and get_suggestions in jquery.Spellchecker.js
/* Config
*************************/
var defaultConfig = {
lang: 'en',
webservice: {
path: 'SpellCheckerService.asmx/get_incorrect_words'
//,driver: 'LabNET'
},
local: {
requestError: 'There was an error processing the request.',
ignoreWord: 'Ignore word',
ignoreAll: 'Ignore all',
ignoreForever: 'Add to dictionary',
loading: 'Loading...',
noSuggestions: '(No suggestions)'
},
suggestBox: {
numWords: 5,
position: 'above',
offset: 2,
appendTo: null
},
incorrectWords: {
container: 'body', //selector
position: null //function
}
};
var pluginName = 'spellchecker';
...
/* Spellchecker web service
*************************/
var WebService = function(config) {
this.config = config;
this.defaultConfig = {
url: config.webservice.path,
//contentType: "application/json; charset=utf-8",
type: 'POST',
dataType: 'text',
cache: false,
data: JSON.stringify({
lang: config.lang,
driver: config.webservice.driver
}, null,2) ,
error: function() {
alert(config.local.requestError);
}.bind(this)
};
};
WebService.prototype.makeRequest = function(config) {
var defaultConfig = $.extend(true, {}, this.defaultConfig);
return $.ajax($.extend(true, defaultConfig, config));
};
WebService.prototype.checkWords = function (text, callback) {
//action: 'get_incorrect_words',
//JSON.stringify({
// text: text
//}, null, 2)
return this.makeRequest(
{
data: { words: text },
success: callback
});
};
WebService.prototype.getSuggestions = function (word, callback) {
//action: 'get_suggestions',
return this.makeRequest({
data: JSON.stringify({
word: word
}, null, 2),
success: callback
});
};

I have found a solution for the issue and
below is the webservice which returns the JSON response for the jquery spell checker
This code is the modified verion of code found in
github.com/jackmyang/jQuery-Spell-Checker-for-ASP.NET
/// <summary>
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Web;
using System.Xml;
< %# WebHandler Language="C#" Class="JQuerySpellCheckerHandler2" %>
/// <summary>
/// jQuery spell checker http handler class. Original server-side code was written by Richard Willis in PHP.
/// This is a version derived from the original design and implemented for ASP.NET platform.
///
/// It's very easy to use this handler with ASP.NET WebForm or MVC. Simply do the following steps:
/// 1. Include project jquery.spellchecker assembly in the website as a reference
/// 2. Include the httphandler node in the system.web node for local dev or IIS 6 or below
/// <example>
/// <![CDATA[
/// <system.web>
/// <httpHandlers>
/// <add verb="GET,HEAD,POST" type="jquery.spellchecker.JQuerySpellCheckerHandler" path="JQuerySpellCheckerHandler.ashx"/>
/// </httpHandlers>
/// </system.web>
/// ]]>
/// </example>
/// 3. If IIS7 is the target web server, also need to include the httphandler node in the system.webServer node
/// <example>
/// <![CDATA[
/// <system.webServer>
/// <handlers>
/// <add verb="GET,HEAD,POST" name="JQuerySpellCheckerHandler" type="jquery.spellchecker.JQuerySpellCheckerHandler" path="JQuerySpellCheckerHandler.ashx"/>
/// </handlers>
/// </system.webServer>
/// ]]>
/// </example>
/// 4. On the web page which included the spell checker, set the 'url' property to '~/JQuerySpellCheckerHandler.ashx'
/// <example>
/// <![CDATA[
/// $("#text-content")
/// .spellchecker({
/// url: "~/JQuerySpellCheckerHandler.ashx",
/// lang: "en",
/// engine: "google",
/// suggestBoxPosition: "above"
/// })
/// ]]>
/// </example>
/// </summary>
/// <remarks>
/// Manipulations of XmlNodeList is used for compatibility concern with lower version of .NET framework,
/// alternatively, they can be simplified using 'LINQ for XML' if .NET 3.5 or higher is available.
/// </remarks>
public class JQuerySpellCheckerHandler2 : IHttpHandler
{
#region fields
// in case google changes url, value of GoogleSpellCheckRpc can be stored in web.config instead to avoid code re-compilation
private const string GoogleSpellCheckRpc = "https://www.google.com/tbproxy/spell?";
private const string GoogleFlagTextAlreadClipped = "textalreadyclipped";
private const string GoogleFlagIgnoreDups = "ignoredups";
private const string GoogleFlagIgnoreDigits = "ignoredigits";
private const string GoogleFlagIgnoreAllCaps = "ignoreallcaps";
#endregion
#region properties
/// <summary>
/// Gets or sets a value indicating whether [ignore duplicated words].
/// </summary>
/// <value><c>true</c> if [ignore dups]; otherwise, <c>false</c>.</value>
private bool IgnoreDups { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [ignore digits].
/// </summary>
/// <value><c>true</c> if [ignore digits]; otherwise, <c>false</c>.</value>
private bool IgnoreDigits { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [ignore all capitals].
/// </summary>
/// <value><c>true</c> if [ignore all caps]; otherwise, <c>false</c>.</value>
private bool IgnoreAllCaps { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [text alread clipped].
/// </summary>
/// <value><c>true</c> if [text alread clipped]; otherwise, <c>false</c>.</value>
private bool TextAlreadClipped { get; set; }
#endregion
#region Implementation of IHttpHandler
/// <summary>
/// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler"/> interface.
/// </summary>
/// <param name="context">An <see cref="T:System.Web.HttpContext"/> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.
/// </param>
public void ProcessRequest(HttpContext context)
{
string engine = context.Request.Form[1];
string lang = context.Request.Form["lang"];
string text = context.Request.Form[3];
string suggest = context.Request.Form[2];
SetSwitches(context);
string result = SpellCheck(text, lang, engine, suggest);
context.Response.ContentType = "application/js";
string jsonStr = "{\"outcome\":\"success\",\"data\":[" + result + "]}";
if (suggest == "get_incorrect_words")
{
context.Response.Write(jsonStr);
}
else
{
context.Response.Write(result);
}
}
/// <summary>
/// Gets a value indicating whether another request can use the <see cref="T:System.Web.IHttpHandler"/> instance.
/// </summary>
/// <returns>
/// true if the <see cref="T:System.Web.IHttpHandler"/> instance is reusable; otherwise, false.
/// </returns>
public bool IsReusable
{
get { return false; }
}
#endregion
#region private methods
/// <summary>
/// Spells the check.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="lang">The lang.</param>
/// <param name="engine">The engine.</param>
/// <param name="suggest">The suggest.</param>
/// <returns></returns>
private string SpellCheck(string text, string lang, string engine, string suggest)
{
if (0 == string.Compare(suggest, "undefined", StringComparison.OrdinalIgnoreCase))
{
suggest = string.Empty;
}
if (0 != string.Compare(engine, "google", true))
{
throw new NotImplementedException("Only google spell check engine is support at this moment.");
}
string xml;
List<string> result;
if (string.IsNullOrEmpty(suggest) || suggest == "get_incorrect_words")
{
xml = GetSpellCheckRequest(text, lang);
result = GetListOfMisspelledWords(xml, text);
}
else
{
xml = GetSpellCheckRequest(text, lang);
result = GetListOfSuggestWords(xml, text);
}
return ConvertStringListToJavascriptArrayString(result);
}
/// <summary>
/// Sets the boolean switch.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="queryStringParameter">The query string parameter.</param>
/// <returns></returns>
private static bool SetBooleanSwitch(HttpContext context, string queryStringParameter)
{
byte tryParseZeroOne;
string queryStringValue = context.Request.QueryString[queryStringParameter];
if (!string.IsNullOrEmpty(queryStringValue) && byte.TryParse(queryStringValue, out tryParseZeroOne))
{
if (1 < tryParseZeroOne || 0 > tryParseZeroOne)
{
throw new InvalidOperationException(string.Format("Query string parameter '{0}' only supports values of 1 and 0.", queryStringParameter));
}
return tryParseZeroOne == 1;
}
return false;
}
/// <summary>
/// Gets the list of suggest words.
/// </summary>
/// <param name="xml">The source XML.</param>
/// <param name="suggest">The word to be suggested.</param>
/// <returns></returns>
private static List<string> GetListOfSuggestWords(string xml, string suggest)
{
if (string.IsNullOrEmpty(xml) || string.IsNullOrEmpty(suggest))
{
return null;
}
//
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(xml);
if (!xdoc.HasChildNodes)
{
return null;
}
XmlNodeList nodeList = xdoc.SelectNodes("//c");
if (null == nodeList || 0 >= nodeList.Count)
{
return null;
}
List<string> list = new List<string>();
foreach (XmlNode node in nodeList)
{
list.AddRange(node.InnerText.Split('\t'));
return list;
}
return list;
}
/// <summary>
/// Gets the list of misspelled words.
/// </summary>
/// <param name="xml">The source XML.</param>
/// <param name="text">The text.</param>
/// <returns></returns>
private static List<string> GetListOfMisspelledWords(string xml, string text)
{
if (string.IsNullOrEmpty(xml) || string.IsNullOrEmpty(text))
{
return null;
}
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(xml);
if (!xdoc.HasChildNodes)
{
return null;
}
XmlNodeList nodeList = xdoc.SelectNodes("//c");
if (null == nodeList || 0 >= nodeList.Count)
{
return null;
}
List<string> list = new List<string>();
foreach (XmlNode node in nodeList)
{
int offset = Convert.ToInt32(node.Attributes["o"].Value);
int length = Convert.ToInt32(node.Attributes["l"].Value);
list.Add(text.Substring(offset, length));
}
return list;
}
/// <summary>
/// Constructs the request URL.
/// </summary>
/// <param name="text">The text which may contain multiple words.</param>
/// <param name="lang">The language.</param>
/// <returns></returns>
private static string ConstructRequestUrl(string text, string lang)
{
if (string.IsNullOrEmpty(text))
{
return string.Empty;
}
lang = string.IsNullOrEmpty(lang) ? "en" : lang;
return string.Format("{0}lang={1}&text={2}", GoogleSpellCheckRpc, lang, text);
}
/// <summary>
/// Converts the C# string list to Javascript array string.
/// </summary>
/// <param name="list">The list.</param>
/// <returns></returns>
private static string ConvertStringListToJavascriptArrayString(ICollection<string> list)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("[");
if (null != list && 0 < list.Count)
{
bool showSeperator = false;
foreach (string word in list)
{
if (showSeperator)
{
stringBuilder.Append(",");
}
stringBuilder.AppendFormat("\"{0}\"", word);
showSeperator = true;
}
}
stringBuilder.Append("]");
return stringBuilder.ToString();
}
/// <summary>
/// Sets the switches.
/// </summary>
/// <param name="context">The context.</param>
private void SetSwitches(HttpContext context)
{
IgnoreAllCaps = SetBooleanSwitch(context, GoogleFlagIgnoreAllCaps);
IgnoreDigits = SetBooleanSwitch(context, GoogleFlagIgnoreDigits);
IgnoreDups = SetBooleanSwitch(context, GoogleFlagIgnoreDups);
TextAlreadClipped = SetBooleanSwitch(context, GoogleFlagTextAlreadClipped);
}
/// <summary>
/// Requests the spell check and get the result back.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="lang">The language.</param>
/// <returns></returns>
private string GetSpellCheckRequest(string text, string lang)
{
string requestUrl = ConstructRequestUrl(text, lang);
string requestContentXml = ConstructSpellRequestContentXml(text);
byte[] buffer = Encoding.UTF8.GetBytes(requestContentXml);
WebClient webClient = new WebClient();
webClient.Headers.Add("Content-Type", "text/xml");
try
{
byte[] response = webClient.UploadData(requestUrl, "POST", buffer);
return Encoding.UTF8.GetString(response);
}
catch (ArgumentException)
{
return string.Empty;
}
}
/// <summary>
/// Constructs the spell request content XML.
/// </summary>
/// <param name="text">The text which may contain multiple words.</param>
/// <returns></returns>
private string ConstructSpellRequestContentXml(string text)
{
XmlDocument doc = new XmlDocument(); // Create the XML Declaration, and append it to XML document
XmlDeclaration declaration = doc.CreateXmlDeclaration("1.0", null, null);
doc.AppendChild(declaration);
XmlElement root = doc.CreateElement("spellrequest");
root.SetAttribute(GoogleFlagTextAlreadClipped, TextAlreadClipped ? "1" : "0");
root.SetAttribute(GoogleFlagIgnoreDups, IgnoreDups ? "1" : "0");
root.SetAttribute(GoogleFlagIgnoreDigits, IgnoreDigits ? "1" : "0");
root.SetAttribute(GoogleFlagIgnoreAllCaps, IgnoreAllCaps ? "1" : "0");
doc.AppendChild(root);
XmlElement textElement = doc.CreateElement("text");
textElement.InnerText = text;
root.AppendChild(textElement);
return doc.InnerXml;
}
#endregion
}
Also you can use this javascript:
// Replace the Spellchecker.php path with Asp.net ashx path
spellchecker = new $.SpellChecker(body, {
lang: 'en',
parser: 'html',
webservice: {
path: "../Includes/JS/spellify/JQuerySpellCheckerHandler2.ashx",
driver: 'google'
},
suggestBox: {
position: 'below'
}
});
// Bind spellchecker handler functions
spellchecker.on('check.success', function() {
alert('There are no incorrectly spelt words.');
});
spellchecker.check();

Related

XLabs.Platform not working on UWP

I am using Windows 10 & Visual Studio 2015 for development and targeting Android, iOS, Windows Phone, Windows Universal.
I wanted to use XLabs SecureStorage Service.
I am using XLabs.Platform package 2.3.0-pre02.
at this line i am getting exception (only for UWP)
secureStorage.Store(key, Encoding.UTF8.GetBytes(value));
And Exception Details are :
FileName : System.Runtime.WindowsRuntime, Version=4.0.11.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
HResult : -2146234304
HelpLink : null
InnerException : null
Message : Could not load file or assembly 'System.Runtime.WindowsRuntime, Version=4.0.11.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Source : XLabs.Platform.UWP
SourceTrack : at XLabs.Platform.Services.SecureStorage.d__6.MoveNext()
at System.Runtime.CompilerServices.AsyncVoidMethodBuilder.StartTStateMachine
at XLabs.Platform.Services.SecureStorage.Store(String key, Byte[] dataBytes)
at UWPTest.SecureStorageService.Store(String key, String value, Boolean overwrite)
After some trial and error i am able to run SecureStorage service successfully on Xamarin UWP.
SecureStorage.cs(Code)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ABC.UWP.Common
{
using System;
using System.IO;
using Windows.Storage;
using System.Threading;
using System.Runtime.InteropServices.WindowsRuntime;
using XLabs.Platform.Services;
using Windows.Security.Cryptography.DataProtection;
/// <summary>
/// Implements <see cref="ISecureStorage"/> for WP using <see cref="IsolatedStorageFile"/> and <see cref="ProtectedData"/>.
/// </summary>
public class SecureStorage : ISecureStorage
{
private static Windows.Storage.ApplicationData AppStorage { get { return ApplicationData.Current; } }
private static Windows.Security.Cryptography.DataProtection.DataProtectionProvider _dataProtectionProvider = new DataProtectionProvider();
private readonly byte[] _optionalEntropy;
/// <summary>
/// Initializes a new instance of <see cref="SecureStorage"/>.
/// </summary>
/// <param name="optionalEntropy">Optional password for additional entropy to make encyption more complex.</param>
public SecureStorage(byte[] optionalEntropy)
{
this._optionalEntropy = optionalEntropy;
}
/// <summary>
/// Initializes a new instance of <see cref="SecureStorage"/>.
/// </summary>
public SecureStorage() : this(null)
{
}
#region ISecureStorage Members
/// <summary>
/// Stores the specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="dataBytes">The data bytes.</param>
public async void Store(string key, byte[] dataBytes)
{
//var mutex = new Mutex(false, key);
using (var mutex = new Mutex(false, key))
{
try
{
mutex.WaitOne();
var buffer = dataBytes.AsBuffer();
if (_optionalEntropy != null)
{
buffer = await _dataProtectionProvider.ProtectAsync(buffer);
}
var file = await AppStorage.LocalFolder.CreateFileAsync(key, CreationCollisionOption.ReplaceExisting);
await FileIO.WriteBufferAsync(file, buffer);
}
catch (Exception ex)
{
throw new Exception(string.Format("No entry found for key {0}.", key), ex);
}
}
//finally
//{
// mutex.ReleaseMutex();
//}
}
/// <summary>
/// Retrieves the specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <returns>System.Byte[].</returns>
/// <exception cref="System.Exception"></exception>
public byte[] Retrieve(string key)
{
var mutex = new Mutex(false, key);
try
{
mutex.WaitOne();
return Task.Run(async () =>
{
var file = await AppStorage.LocalFolder.GetFileAsync(key);
var buffer = await FileIO.ReadBufferAsync(file);
if (_optionalEntropy != null)
{
buffer = _dataProtectionProvider.UnprotectAsync(buffer).GetResults();
}
return buffer.ToArray();
}).Result;
}
catch (Exception ex)
{
throw new Exception(string.Format("No entry found for key {0}.", key), ex);
}
finally
{
mutex.ReleaseMutex();
}
}
/// <summary>
/// Deletes the specified key.
/// </summary>
/// <param name="key">The key.</param>
public void Delete(string key)
{
var mutex = new Mutex(false, key);
try
{
mutex.WaitOne();
Task.Run(async () =>
{
var file = await AppStorage.LocalFolder.GetFileAsync(key);
await file.DeleteAsync();
});
}
finally
{
mutex.ReleaseMutex();
}
}
/// <summary>
/// Checks if the storage contains a key.
/// </summary>
/// <param name="key">The key to search.</param>
/// <returns>True if the storage has the key, otherwise false. </returns>
public bool Contains(string key)
{
try
{
return Task.Run(async() => await AppStorage.LocalFolder.GetFileAsync(key)).Result.IsAvailable;
}
catch
{
return false;
}
}
#endregion
}
}

Show / Hide checkbox in Xamarin Forms

I am trying to figure out a way to make checkbox appear on button click on a page.
It's invisible by default, because I've set checkBox.Visibility = Android.Views.ViewStates.Invisible; in my custom renderer.
I have a button in the page content and a checkbox in the template which resides in pages resources.
From my ViewModel I am able to invoke PropertyChanged in CheckBox control where I can see the old and new value correctly set.
But I need a way to set it on the ViewRenderer. I'm guessing that it needs to handle some kind of event similar to CheckedChanged.
ViewModel
CheckBox c = new CheckBox { IsCheckBoxVisible=true,IsVisible=true };
CheckBox control
public class CheckBox : View
{
/// <summary>
/// The checked state property.
/// </summary>
public static readonly BindableProperty CheckedProperty =
BindableProperty.Create<CheckBox, bool>(
p => p.Checked, false, BindingMode.TwoWay, propertyChanged: OnCheckedPropertyChanged);
**public static readonly BindableProperty IsCheckBoxVisibleProperty =
BindableProperty.Create<CheckBox, bool>(
p => p.IsCheckBoxVisible, false, BindingMode.OneWay, propertyChanged: OnVisibilityPropertyChanged);**
/// <summary>
/// The checked text property.
/// </summary>
public static readonly BindableProperty CheckedTextProperty =
BindableProperty.Create<CheckBox, string>(
p => p.CheckedText, string.Empty, BindingMode.TwoWay);
/// <summary>
/// The unchecked text property.
/// </summary>
public static readonly BindableProperty UncheckedTextProperty =
BindableProperty.Create<CheckBox, string>(
p => p.UncheckedText, string.Empty);
/// <summary>
/// The default text property.
/// </summary>
public static readonly BindableProperty DefaultTextProperty =
BindableProperty.Create<CheckBox, string>(
p => p.Text, string.Empty);
/// <summary>
/// Identifies the TextColor bindable property.
/// </summary>
///
/// <remarks/>
public static readonly BindableProperty TextColorProperty =
BindableProperty.Create<CheckBox, Color>(
p => p.TextColor, Color.Default);
/// <summary>
/// The font size property
/// </summary>
public static readonly BindableProperty FontSizeProperty =
BindableProperty.Create<CheckBox, double>(
p => p.FontSize, -1);
/// <summary>
/// The font name property.
/// </summary>
public static readonly BindableProperty FontNameProperty =
BindableProperty.Create<CheckBox, string>(
p => p.FontName, string.Empty);
/// <summary>
/// The checked changed event.
/// </summary>
public event EventHandler<EventArgs<bool>> CheckedChanged;
**public event EventHandler<EventArgs<bool>> VisibilityChanged;**
/// <summary>
/// Gets or sets a value indicating whether the control is checked.
/// </summary>
/// <value>The checked state.</value>
public bool Checked
{
get
{
return this.GetValue<bool>(CheckedProperty);
}
set
{
if (this.Checked != value)
{
this.SetValue(CheckedProperty, value);
this.CheckedChanged.Invoke(this, value);
}
}
}
**public bool IsCheckBoxVisible
{
get
{
return this.GetValue<bool>(IsCheckBoxVisibleProperty);
}
set
{
if (this.IsCheckBoxVisible != value)
{
this.SetValue(IsCheckBoxVisibleProperty, value);
this.VisibilityChanged.Invoke(this, value);
//OnPropertyChanged("IsCheckBoxVisible");
}
}
}**
/// <summary>
/// Gets or sets a value indicating the checked text.
/// </summary>
/// <value>The checked state.</value>
/// <remarks>
/// Overwrites the default text property if set when checkbox is checked.
/// </remarks>
public string CheckedText
{
get
{
return this.GetValue<string>(CheckedTextProperty);
}
set
{
this.SetValue(CheckedTextProperty, value);
}
}
/// <summary>
/// Gets or sets a value indicating whether the control is checked.
/// </summary>
/// <value>The checked state.</value>
/// <remarks>
/// Overwrites the default text property if set when checkbox is checked.
/// </remarks>
public string UncheckedText
{
get
{
return this.GetValue<string>(UncheckedTextProperty);
}
set
{
this.SetValue(UncheckedTextProperty, value);
}
}
/// <summary>
/// Gets or sets the text.
/// </summary>
public string DefaultText
{
get
{
return this.GetValue<string>(DefaultTextProperty);
}
set
{
this.SetValue(DefaultTextProperty, value);
}
}
/// <summary>
/// Gets or sets the color of the text.
/// </summary>
/// <value>The color of the text.</value>
public Color TextColor
{
get
{
return this.GetValue<Color>(TextColorProperty);
}
set
{
this.SetValue(TextColorProperty, value);
}
}
/// <summary>
/// Gets or sets the size of the font.
/// </summary>
/// <value>The size of the font.</value>
public double FontSize
{
get
{
return (double)GetValue(FontSizeProperty);
}
set
{
SetValue(FontSizeProperty, value);
}
}
/// <summary>
/// Gets or sets the name of the font.
/// </summary>
/// <value>The name of the font.</value>
public string FontName
{
get
{
return (string)GetValue(FontNameProperty);
}
set
{
SetValue(FontNameProperty, value);
}
}
/// <summary>
/// Gets the text.
/// </summary>
/// <value>The text.</value>
public string Text
{
get
{
return this.Checked
? (string.IsNullOrEmpty(this.CheckedText) ? this.DefaultText : this.CheckedText)
: (string.IsNullOrEmpty(this.UncheckedText) ? this.DefaultText : this.UncheckedText);
}
}
/// <summary>
/// Called when [checked property changed].
/// </summary>
/// <param name="bindable">The bindable.</param>
/// <param name="oldvalue">if set to <c>true</c> [oldvalue].</param>
/// <param name="newvalue">if set to <c>true</c> [newvalue].</param>
private static void OnCheckedPropertyChanged(BindableObject bindable, bool oldvalue, bool newvalue)
{
var checkBox = (CheckBox)bindable;
checkBox.Checked = newvalue;
}
**private static void OnVisibilityPropertyChanged(BindableObject bindable, bool oldvalue, bool newvalue)
{
var checkBox = (CheckBox)bindable;
checkBox.IsCheckBoxVisible = newvalue;
}**
}
CheckBoxRenderer
protected override void OnElementChanged(ElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (this.Control == null)
{
var checkBox = new Android.Widget.CheckBox(this.Context);
checkBox.Visibility = Android.Views.ViewStates.Invisible;
checkBox.CheckedChange += CheckBoxCheckedChange;
defaultTextColor = checkBox.TextColors;
this.SetNativeControl(checkBox);
}
Control.Text = e.NewElement.Text;
Control.Checked = e.NewElement.Checked;
UpdateTextColor();
if (e.NewElement.FontSize > 0)
{
Control.TextSize = (float)e.NewElement.FontSize;
}
if (!string.IsNullOrEmpty(e.NewElement.FontName))
{
Control.Typeface = TrySetFont(e.NewElement.FontName);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
switch (e.PropertyName)
{
case "Checked":
Control.Text = Element.Text;
Control.Checked = Element.Checked;
break;
case "TextColor":
UpdateTextColor();
break;
case "FontName":
if (!string.IsNullOrEmpty(Element.FontName))
{
Control.Typeface = TrySetFont(Element.FontName);
}
break;
case "FontSize":
if (Element.FontSize > 0)
{
Control.TextSize = (float)Element.FontSize;
}
break;
case "CheckedText":
case "UncheckedText":
Control.Text = Element.Text;
break;
** case "IsCheckBoxVisible":
if(Element.IsCheckBoxVisible==true)
{
Control.Visibility = Android.Views.ViewStates.Visible;
}
else
{
Control.Visibility = Android.Views.ViewStates.Invisible;
}
break;**
default:
System.Diagnostics.Debug.WriteLine("Property change for {0} has not been implemented.", e.PropertyName);
break;
}
}
So this should actually be really simple. right now you have IsCheckBoxVisibleProperty, and you can get rid of it all together. The Xamarin.Forms.View already has an IsVisible property, and each platform specific renderer (VisualElementRenderer) knows how to handle visibility.
Therefore you can do this without issue.
var checkbox = new Checkbox();
checkbox .SetBinding (Checkbox.IsVisibleProperty, "IsCheckboxVisible");
Or in your XAML
<controls:Checkbox IsVisible="{Binding IsCheckboxVisible}" />
Of course this assumes you have a ViewModel similar to.
public class MyViewModel : BaseViewModel
{
private bool _isCheckboxVisible;
public bool IsCheckboxVisible
{
get { return _isCheckboxVisible; }
set { SetField(ref _isCheckboxVisible, value); }
}
}

Yammer Authentication with HttpWebRequest

I am currently working on a project that requires using the Yammer API. The intent is to bypass using a browser, and use HttpWebRequest to do all authentication. Originally, this was working for me, but now I get a 404 error when I try to call GetResponse().
For my URL, I have tried using
https://www.yammer.com/session?client_id={CLIENT_ID}
as well as
https://www.yammer.com/session
using (var stream = webrequest.GetRequestStream())
{
stream.Write(postdata, 0, postdata.Length);
}
try
{
webresponse = webrequest.GetResponse() as HttpWebResponse;
}
catch (WebException ex)
{
webresponse = ex.Response as HttpWebResponse;
}
Have they changed the URL or am I doing something wrong?
The following is my code snippet for yammer authentication. Steve Pescha's article - http://blogs.technet.com/b/speschka/archive/2013/10/05/using-the-yammer-api-in-a-net-client-application.aspx explains how to perform Programmatic yammer authentication. I have customized it according to my needs.
public class YammerSession
{
#region Variables
/// <summary>
/// The client identifier
/// </summary>
private readonly string clientId = "XXXXXXXX";
/// <summary>
/// client secret
/// </summary>
private readonly string clientSecret = "XXXXXXXX";
/// <summary>
/// Cookie container that stores yammer authentication information
/// </summary>
private CookieContainer cookieContainer = new CookieContainer(2);
/// <summary>
/// The user code sent in response to login request
/// </summary>
private string userCode;
/// <summary>
/// The user email
/// </summary>
private string email;
/// <summary>
/// The user password
/// </summary>
private SecureString password;
#endregion
#region Methods
/// <summary>
/// Gets the supported yammer version
/// </summary>
public static int SupportedVersion
{
get
{
return 1;
}
}
/// <summary>
/// Gets the client id.
/// </summary>
public string ClientId
{
get
{
return this.clientId;
}
}
/// <summary>
/// Gets the authenticity token.
/// </summary>
/// <value>
/// The authenticity token.
/// </value>
public string AuthenticityToken { get; private set; }
/// <summary>
/// Gets the token.
/// </summary>
/// <value>
/// The token.
/// </value>
public string Token { get; private set; }
/// <summary>
/// Connects the specified connection.
/// </summary>
public override void Connect()
{
this.InternalLogin(this.Connection.User, this.Connection.Password);
}
/// <summary>
/// Disconnects this instance.
/// </summary>
public override void Disconnect()
{
// Log out
this.InternalLogout(this.Connection.Address);
}
/// <summary>
/// Creates the web request to a service endpoint.
/// </summary>
/// <param name="serviceEndpoint">The service endpoint.</param>
/// <returns>
/// A new HTTP web request.
/// </returns>
public string GetEndpoint(string serviceEndpoint)
{
// Get the uri
var requestUri = string.Format("{0}/api/v{1}/{2}", this.Connection.Address, SupportedVersion, serviceEndpoint);
// return the result
return requestUri;
}
/// <summary>
/// Connects the specified email.
/// </summary>
/// <param name="email">The email.</param>
/// <param name="password">The password.</param>
private void InternalLogin(string email, SecureString password)
{
this.email = email;
this.password = password;
// Get the user code.
this.GetUserCode();
// Now get the bearer token
this.GetBearerToken(this.userCode);
}
/// <summary>
/// Gets the user code.
/// </summary>
private void GetUserCode()
{
string yammerAuthUrl = string.Format("https://www.yammer.com/dialog/oauth?client_id={0}", this.clientId);
string yammerSessionUrl = string.Format("https://www.yammer.com/session?client_id={0}", this.clientId);
// The authenticity token
string authenticityToken = string.Empty;
// Make a get request to Yammer authentication endpoint and get the response
using (HttpWebResponse webResponse = this.MakeGetRequestToEndPoint(yammerAuthUrl))
{
// Set the cookies
this.SetCookies(webResponse);
// Look for authenticity token
authenticityToken = this.GetAuthenticityToken(SessionHelper.ConvertResponseStreamToString(webResponse, Encoding.UTF8));
}
if (!string.IsNullOrEmpty(authenticityToken))
{
// Construct the post body with user login information
string postBody = string.Format(
"{0}{1}{2}{3}{4}{5}{6}",
"utf8=%E2%9C%93&authenticity_token=",
HttpUtility.UrlEncode(authenticityToken),
"&network_permalink=&login=",
HttpUtility.UrlEncode(this.email),
"&password=",
HttpUtility.UrlEncode(this.password.ConvertToUnsecureString()),
"&remember_me=off");
// Make the first post for User Code
HttpWebResponse sessionPostWebResponse = this.MakePostRequestToEndPoint(postBody, yammerSessionUrl);
string postResults = this.GetResponseAsString(sessionPostWebResponse);
// Get the next auth token that was returned. This will be used for logout purposes
this.AuthenticityToken = this.GetAuthenticityToken(postResults);
using (HttpWebResponse webResponse = this.MakeGetRequestToEndPoint(yammerAuthUrl, true))
{
// Now look for the query string and set the user code
this.userCode = webResponse.ResponseUri.Query;
// Check whether we are in Authorization Page
if (this.userCode.IndexOf("?client_id") >= 0)
{
// Construct the yammer network name
string yammerNetworkName = webResponse.ResponseUri.AbsolutePath.Substring(0, webResponse.ResponseUri.AbsolutePath.ToLower().IndexOf("dialog/"));
// Construct the yammer decision url
string yammerUserAuthDecisionUrl = string.Format(
"{0}{1}{2}{3}{4}",
"https://www.yammer.com",
yammerNetworkName,
"oauth2/decision?client_id=",
this.clientId,
"&redirect_uri=https%3A%2F%2Fwww.yammer.com&response_type=code");
// Construct the Payload for authorization page
string payLoad = "utf8=%E2%9C%93&authenticity_token=" + HttpUtility.UrlEncode(this.AuthenticityToken) + "&allow=Allow";
// Authorize the app by posting the request
using (HttpWebResponse decisionPostWebResponse = this.MakePostRequestToEndPoint(payLoad, yammerUserAuthDecisionUrl))
{
// Reset the user Code
this.userCode = decisionPostWebResponse.ResponseUri.Query;
}
}
// App should have been granted access at this point if it did not already have access.
// Now check whether the code is present in the query string
if (this.userCode.IndexOf("?code=") < 0)
{
throw new ArgumentException(Properties.ErrorMessges.UnableToLogin);
}
this.userCode = this.userCode.Replace("?code=", string.Empty);
}
}
}
/// <summary>
/// Get Yammer Authenticity Token
/// </summary>
/// <param name="rawHtml">The Yammer response that was got after posting to yammer endpoint</param>
/// <returns>The Yammer authenticity token</returns>
private string GetAuthenticityToken(string rawHtml)
{
string result = string.Empty;
int at = rawHtml.IndexOf("<meta name=\"authenticity_token\" id=\"authenticity_token\"");
if (at > -1)
{
// Get the authenticity token string
int et = rawHtml.IndexOf("/>", at + 1);
string tokenText = rawHtml.Substring(at, et - at);
// Get the token value
int ts = tokenText.IndexOf("content=");
int es = tokenText.LastIndexOf("\"");
result = tokenText.Substring(ts + 9, es - ts - 9);
}
return result;
}
/// <summary>
/// Perform a get request to an endpoint and return the Http response
/// </summary>
/// <param name="endPoint">The endpoint to make the request</param>
/// <param name="addCookies">Should cookies be added to the request</param>
/// <returns>The Http Web Response</returns>
private HttpWebResponse MakeGetRequestToEndPoint(string endPoint, bool addCookies = false)
{
HttpWebRequest webRequest = WebRequest.CreateHttp(endPoint);
webRequest.Method = "GET";
if (addCookies)
{
webRequest.CookieContainer = this.cookieContainer;
}
return (HttpWebResponse)webRequest.GetResponse();
}
/// <summary>
/// Read the cookies from the web response object and store it in the cookie container instance variable
/// </summary>
/// <param name="webResponse">The Web Response object</param>
private void SetCookies(HttpWebResponse webResponse)
{
const string YAMTRAK_COOKIE = "yamtrak_id";
const string SESSION_COOKIE = "_workfeed_session_id";
const string LOGIN_CSRF_TOKEN_COOKIE = "login_csrf_token";
string cookies = webResponse.Headers["Set-Cookie"];
if (string.IsNullOrEmpty(cookies))
{
this.cookieContainer = new CookieContainer();
}
else
{
// Split the cookie based on , and ;
string[] sepChar = new string[2];
sepChar[0] = ",";
sepChar[1] = ";";
string[] cookieArray = cookies.Split(sepChar, StringSplitOptions.None);
// Declare variables to hold the different types of cookies
string login_csrf_token = string.Empty;
string yammerTrakToken = string.Empty;
string sessionToken = string.Empty;
// Parse the cookie array and store the cookies in the array
for (int i = 0; i < cookieArray.Length; i++)
{
if (cookieArray[i].IndexOf(YAMTRAK_COOKIE) >= 0)
{
yammerTrakToken = cookieArray[i];
}
if (cookieArray[i].IndexOf(SESSION_COOKIE) >= 0)
{
sessionToken = cookieArray[i];
}
if (cookieArray[i].IndexOf(LOGIN_CSRF_TOKEN_COOKIE) >= 0)
{
login_csrf_token = cookieArray[i];
}
}
// Create the cookie container
this.cookieContainer = new CookieContainer();
// Get the value for each of the cookie and add it to the cookie container
if (!string.IsNullOrWhiteSpace(yammerTrakToken))
{
yammerTrakToken = yammerTrakToken.Substring(YAMTRAK_COOKIE.Length + 1);
this.cookieContainer.Add(new Cookie(YAMTRAK_COOKIE, yammerTrakToken, "/", "www.yammer.com"));
}
if (!string.IsNullOrWhiteSpace(sessionToken))
{
sessionToken = sessionToken.Substring(SESSION_COOKIE.Length + 1);
this.cookieContainer.Add(new Cookie(SESSION_COOKIE, sessionToken, "/", "www.yammer.com"));
}
if (!string.IsNullOrWhiteSpace(login_csrf_token))
{
login_csrf_token = login_csrf_token.Substring(LOGIN_CSRF_TOKEN_COOKIE.Length + 1);
this.cookieContainer.Add(new Cookie(LOGIN_CSRF_TOKEN_COOKIE, login_csrf_token, "/", "www.yammer.com"));
}
}
}
/// <summary>
/// Make a post request to an endpoint and return the result
/// </summary>
/// <param name="postBody">The post request payload</param>
/// <param name="endPoint">The endpoint</param>
/// <returns>The response got from the server</returns>
private HttpWebResponse MakePostRequestToEndPoint(string postBody, string endPoint)
{
string responseString = string.Empty;
HttpWebRequest webRequest = WebRequest.CreateHttp(endPoint);
webRequest.Method = "POST";
webRequest.CookieContainer = this.cookieContainer;
webRequest.ContentType = "application/x-www-form-urlencoded";
SessionHelper.WritePayLoadToWebRequest(webRequest, postBody);
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
return webResponse;
}
/// <summary>
/// Get Response as string
/// </summary>
/// <param name="webResponse">The http web response object</param>
/// <returns>The web response string</returns>
/// <remarks>The Http Response object would be disposed after use</remarks>
private string GetResponseAsString(HttpWebResponse webResponse)
{
string responseString = string.Empty;
using (webResponse)
{
responseString = SessionHelper.ConvertResponseStreamToString(webResponse, Encoding.UTF8);
}
return responseString;
}
/// <summary>
/// Gets the user code.
/// </summary>
/// <param name="userCode">The user code.</param>
/// <exception cref="System.TimeoutException">Waiting for login page load.
/// or
/// Waiting for post login page load.</exception>
private void GetBearerToken(string userCode)
{
string formatUri = string.Format("https://www.yammer.com/oauth2/access_token.json?client_id={0}&client_secret={1}&code={2}", this.clientId, this.clientSecret, userCode);
Uri yammerUri = new Uri(formatUri);
WebRequest webRequest = WebRequest.Create(yammerUri);
webRequest.Method = "GET";
using (WebResponse response = webRequest.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
DataContractJsonSerializer seralizer = new DataContractJsonSerializer(typeof(Model.JSON.Yammer.AccessTokenResponse));
Model.JSON.Yammer.AccessTokenResponse accessTokenResponse = (Model.JSON.Yammer.AccessTokenResponse)seralizer.ReadObject(responseStream);
if (string.IsNullOrWhiteSpace(accessTokenResponse.access_token.token))
{
throw new InvalidOperationException("Unable to extract Yammer.com authorization bearer token.");
}
// Set the bearer token
this.Token = accessTokenResponse.access_token.token;
}
}
}
/// <summary>
/// Internal logout.
/// </summary>
/// <param name="address">The address.</param>
private void InternalLogout(string address)
{
string formatUri = string.Format("{0}/logout?from=nav", address);
Uri yammerUri = new Uri(formatUri);
// Create request
var request = HttpWebRequest.CreateHttp(yammerUri);
// POST
request.Method = "POST";
// Set the cookie container
request.CookieContainer = this.cookieContainer;
// Sent the request body
request.ContentType = "application/x-www-form-urlencoded";
string requestBody = string.Format(
"authenticity_token={0}&_method=delete",
HttpUtility.UrlEncode(this.AuthenticityToken));
byte[] requestBodyUTF8 = Encoding.UTF8.GetBytes(requestBody);
// Set the length before writing the request steam.
request.ContentLength = requestBody.Length;
// Write the request stream
using (var requestStream = request.GetRequestStream())
{
using (StreamWriter streamWrite = new StreamWriter(requestStream))
{
streamWrite.Write(requestBody);
}
}
// Make the request
using (var response = request.GetResponse())
{
// Always read the response
using (Stream responseStream = response.GetResponseStream())
{
}
}
}
#endregion
}
In the above code replace your client Id, client secret, email and password. Then you can use the connect method to get the bearer token and disconnect to log out of yammer.
Recently yammer changed the number of cookies that were passed back and forth and I have fixed the issue

using cache in mvc application

I've a question regarding cache in mvc web application.
I'd like to use cache to store many lists which are used frequently in this way
List<IncotermDTO> incoterm;
string keyIncoterm = "listaIncoterm";
if (!CacheHelper.Get(keyIncoterm, out incoterm))
{
incoterm = BLIncoterm.GetIncoterm(null, null);
CacheHelper.Add(incoterm, keyIncoterm);
}
ViewBag.listaIncoterm = new SelectList(incoterm.OrderBy(x => x.DESCRIPTION), "ID", "DESCRIPTION");
following the tips in this article
http://johnnycoder.com/blog/2008/12/10/c-cache-helper-class/
This is the class helper
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Caching;
namespace GestioneMovimentazioni
{
public static class CacheHelper
{
/// <summary>
/// Insert value into the cache using
/// appropriate name/value pairs
/// </summary>
/// <typeparam name="T">Type of cached item</typeparam>
/// <param name="o">Item to be cached</param>
/// <param name="key">Name of item</param>
public static void Add<T>(T o, string key)
{
// NOTE: Apply expiration parameters as you see fit.
// I typically pull from configuration file.
// In this example, I want an absolute
// timeout so changes will always be reflected
// at that time. Hence, the NoSlidingExpiration.
HttpContext.Current.Cache.Insert(
key,
o,
null,
System.Web.Caching.Cache.NoAbsoluteExpiration,
TimeSpan.FromSeconds(120));
}
/// <summary>
/// Remove item from cache
/// </summary>
/// <param name="key">Name of cached item</param>
public static void Clear(string key)
{
HttpContext.Current.Cache.Remove(key);
}
/// <summary>
/// Check for item in cache
/// </summary>
/// <param name="key">Name of cached item</param>
/// <returns></returns>
public static bool Exists(string key)
{
return HttpContext.Current.Cache[key] != null;
}
/// <summary>
/// Retrieve cached item
/// </summary>
/// <typeparam name="T">Type of cached item</typeparam>
/// <param name="key">Name of cached item</param>
/// <param name="value">Cached value. Default(T) if
/// item doesn't exist.</param>
/// <returns>Cached item as type</returns>
public static bool Get<T>(string key, out T value)
{
try
{
if (!Exists(key))
{
value = default(T);
return false;
}
value = (T)HttpContext.Current.Cache[key];
}
catch
{
value = default(T);
return false;
}
return true;
}
public static T Get<T>(string key) where T : class
{
try
{
return (T)HttpContext.Current.Cache[key];
}
catch
{
return null;
}
}
}
}
This is the question..
This list will be cached for all users of the application or not?
If not, what implementation do you suggest?
HttpContext.Current.Cache is the same for all users. At least as long as you do not use Loadbalancing or Webfarm..

Substutute for FacebookSubscriptionVerify in facebook C# SDk 6.4

In latest version of Facebook C# SDk 6.4. Can we use FacebookSubscriptionVerify Action Method Attribute ? As this is not available in the FacebookClient Class
I was using the older version of Facebok C# SDK in my MVC3 project. Now, After switching to Facebook C# SDK 6.4 this class is not available.
Do we have any substitute for this?
I took a little more time this morning and confirmed that the attribute that you referenced was removed in version 6 (along with tons of other items). Since this project is open source, here is the code for the FacebookSubscriptionVerify ActionFilter that you used to use. For any references to functions within here that I did not include, this version on CodePlex has all of the code available for you to look at: http://facebooksdk.codeplex.com/SourceControl/changeset/view/08cb51f372b5#Source/Facebook.Web/FacebookSubscriptionsHttpHandler.cs
The new version (version 6.X) and the last few branches of version 5 can be found on the GitHub site - https://github.com/facebook-csharp-sdk/facebook-csharp-sdk/tree/master/Source
With the availability of the source code, you should be able to, in tandem with how you were using this function, create your own ActionFilterAttribute that can replicate the functionality that you had previously.
// --------------------------------
// <copyright file="FacebookSubscriptionVerifyAttribute.cs" company="Thuzi LLC (www.thuzi.com)">
// Microsoft Public License (Ms-PL)
// </copyright>
// <author>Nathan Totten (ntotten.com), Jim Zimmerman (jimzimmerman.com) and Prabir Shrestha (prabir.me)</author>
// <license>Released under the terms of the Microsoft Public License (Ms-PL)</license>
// <website>http://facebooksdk.codeplex.com</website>
// ---------------------------------
namespace Facebook.Web.Mvc
{
using System.Web.Mvc;
public class FacebookSubscriptionVerifyAttribute : ActionFilterAttribute
{
public string VerificationToken { get; set; }
public FacebookSubscriptionVerifyAttribute(string verificationToken)
{
VerificationToken = verificationToken;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.ContentType = "text/plain";
var request = filterContext.HttpContext.Request;
var modelState = filterContext.Controller.ViewData.ModelState;
string errorMessage;
if (request.HttpMethod == "GET")
{
if (string.IsNullOrEmpty(VerificationToken))
{
errorMessage = "Verification Token is empty.";
}
else
{
if (FacebookSubscriptionVerifier.VerifyGetSubscription(request, VerificationToken, out errorMessage))
{
return;
}
}
}
else
{
errorMessage = "Invalid http method.";
}
modelState.AddModelError("facebook-subscription", errorMessage);
filterContext.HttpContext.Response.StatusCode = 401;
}
}
}
And the code for the FacebookSubscriptionVerifier Class
namespace Facebook.Web
{
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Web;
/// <summary>
/// Facebook helper methods for web.
/// </summary>
internal static class FacebookSubscriptionVerifier
{
internal const string HTTP_X_HUB_SIGNATURE_KEY = "HTTP_X_HUB_SIGNATURE";
internal static byte[] ComputeHmacSha1Hash(byte[] data, byte[] key)
{
Contract.Requires(data != null);
Contract.Requires(key != null);
Contract.Ensures(Contract.Result<byte[]>() != null);
using (var crypto = new System.Security.Cryptography.HMACSHA1(key))
{
return crypto.ComputeHash(data);
}
}
/// <summary>
/// Verify HTTP_X_HUB_SIGNATURE.
/// </summary>
/// <param name="secret">
/// The secret.
/// </param>
/// <param name="httpXHubSignature">
/// The http x hub signature.
/// </param>
/// <param name="jsonString">
/// The json string.
/// </param>
/// <returns>
/// Returns true if validation is successful.
/// </returns>
internal static bool VerifyHttpXHubSignature(string secret, string httpXHubSignature, string jsonString)
{
Contract.Requires(!string.IsNullOrEmpty(secret));
if (!string.IsNullOrEmpty(httpXHubSignature) && httpXHubSignature.StartsWith("sha1=") && httpXHubSignature.Length > 5 && !string.IsNullOrEmpty(jsonString))
{
// todo: test inner parts
var expectedSignature = httpXHubSignature.Substring(5);
var sha1 = ComputeHmacSha1Hash(Encoding.UTF8.GetBytes(jsonString), Encoding.UTF8.GetBytes(secret));
var hashString = new StringBuilder();
foreach (var b in sha1)
{
hashString.Append(b.ToString("x2"));
}
if (expectedSignature == hashString.ToString())
{
return true;
}
}
return false;
}
/// <summary>
/// Verify HTTP_X_HUB_SIGNATURE for http GET method.
/// </summary>
/// <param name="request">
/// The http request.
/// </param>
/// <param name="verifyToken">
/// The verify token.
/// </param>
/// <param name="errorMessage">
/// The error message.
/// </param>
/// <returns>
/// Returns true if successful otherwise false.
/// </returns>
internal static bool VerifyGetSubscription(HttpRequestBase request, string verifyToken, out string errorMessage)
{
Contract.Requires(request != null);
Contract.Requires(request.HttpMethod == "GET");
Contract.Requires(request.Params != null);
Contract.Requires(!string.IsNullOrEmpty(verifyToken));
errorMessage = null;
if (request.Params["hub.mode"] == "subscribe")
{
if (request.Params["hub.verify_token"] == verifyToken)
{
if (string.IsNullOrEmpty(request.Params["hub.challenge"]))
{
errorMessage = Properties.Resources.InvalidHubChallenge;
}
else
{
return true;
}
}
else
{
errorMessage = Properties.Resources.InvalidVerifyToken;
}
}
else
{
errorMessage = Properties.Resources.InvalidHubMode;
}
return false;
}
/// <summary>
/// Verify HTTP_X_HUB_SIGNATURE for http POST method.
/// </summary>
/// <param name="request">
/// The request.
/// </param>
/// <param name="secret">
/// The secret.
/// </param>
/// <param name="jsonString">
/// The json string.
/// </param>
/// <param name="errorMessage">
/// The error message.
/// </param>
/// <returns>
/// Returns true if successful otherwise false.
/// </returns>
internal static bool VerifyPostSubscription(HttpRequestBase request, string secret, string jsonString, out string errorMessage)
{
Contract.Requires(request != null);
Contract.Requires(request.HttpMethod == "POST");
Contract.Requires(request.Params != null);
Contract.Requires(!string.IsNullOrEmpty(secret));
errorMessage = null;
// signatures looks somewhat like "sha1=4594ae916543cece9de48e3289a5ab568f514b6a"
var signature = request.Params["HTTP_X_HUB_SIGNATURE"];
if (!string.IsNullOrEmpty(signature) && signature.StartsWith("sha1="))
{
var expectedSha1 = signature.Substring(5);
if (string.IsNullOrEmpty(expectedSha1))
{
errorMessage = Properties.Resources.InvalidHttpXHubSignature;
}
else
{
if (string.IsNullOrEmpty(jsonString))
{
errorMessage = Properties.Resources.InvalidJsonString;
return false;
}
var sha1 = ComputeHmacSha1Hash(Encoding.UTF8.GetBytes(jsonString), Encoding.UTF8.GetBytes(secret));
var hashString = new StringBuilder();
foreach (var b in sha1)
{
hashString.Append(b.ToString("x2"));
}
if (expectedSha1 == hashString.ToString())
{
// todo: test
return true;
}
// todo: test
errorMessage = Properties.Resources.InvalidHttpXHubSignature;
}
}
else
{
errorMessage = Properties.Resources.InvalidHttpXHubSignature;
}
return false;
}
}
}

Resources