To implement a DB based user dictionary with RapidSpell Web for ASP.NET Core. The way to do it is by subclassing our UserDictionary class and then making that subclass read/write from/to the DB.
You will also need to write some plumbing code to inject the DBUserDictionary subclass into our API controller.
Firstly, here is the code for a class called DBUserDictionary, you can see that it is just the skeleton, it doesn't actually hit a DB, you would implement that as you see fit, instead it just uses a hardcoded list.
using System;
using System.Collections;
namespace RapidSpellWeb_NetCore_Test.Code
{
///
/// Extends and customises UserDictionary functionality.
/// This is a simple example class, to demonstrate the principle, your own implementation
/// should handle your connections, db setup and exceptions as per the rest of your
/// application.
///
public class DBUserDictionary : Keyoti.RapidSpell.UserDictionary
{
ArrayList wordList;
int wordLimit;
String dictionaryId;
public DBUserDictionary(String dictionaryId, int maxNumWords)
{
wordList = new ArrayList(50);
wordLimit = maxNumWords;
this.dictionaryId = dictionaryId;
//Commented out to simplify and test;
//The purpose of this is to read all user words stored in the DB into the list
//SqlConnection conn = new SqlConnection("Persist Security Info=False;Integrated Security=SSPI;database=pb_mcsis;server=localhost;Connect Timeout=30");
//SqlCommand command = new SqlCommand("select * From DictionaryUser", conn);
//conn.Open();
//SqlDataReader dr = command.ExecuteReader(CommandBehavior.SingleResult);
//while(dr.Read())
// wordList.Add(dr[0]);
//conn.Close();
wordList.Add("ProgressBook");
wordList.Add("WordsBySA");
}
public DBUserDictionary(String dictionaryId) : this(dictionaryId, 100000) { }
public override int ReadAll(ArrayList a)
{
//used by RapidSpell to read the words from the DB.
a.Clear();
wordList.Sort();
a.AddRange(wordList);
return a.Count;
}
public override bool IsValid()
{
//return true if the word list exists and is valid.
//this should return false, if for example there was an sql exception at some point.
//return wordList != null;
//Defaulted to True for test.
return true;
}
public override bool ReloadDictionary()
{
//doing anything necessary here
return true;
}
public override bool AddWord(String word)
{
wordList.Add(word);
wordList.Sort(); //important to keep the list sorted!!
OnListChanged(new ListChangedEventArgs(ListChangedEventArgs.ListChangeOperation.WordAdd, word));
//The purpose of this is to store the word (in "word") in the database.
// SqlConnection conn = new SqlConnection("server=(local)\\NetSDK;database=....;Trusted_Connection=yes");
// SqlCommand command = new SqlCommand("INSERT INTO .............", conn);
// conn.Open();
// command.ExecuteNonQuery();
// conn.Close();
return true;
}
public override bool RemoveWord(string word)
{
wordList.Remove(word);
OnListChanged(new ListChangedEventArgs(ListChangedEventArgs.ListChangeOperation.WordRemove, word));
return base.RemoveWord(word);
}
}
}
To inject that into our code you will need a bit of plumbing, so add this class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Keyoti.RapidSpell;
using RapidSpellWeb_NetCore_Test.Code;
namespace RapidSpellWeb_NetCore_Test
{
public class RapidSpellObjectProvider : Keyoti.RapidSpell.IObjectProvider
{
public UserDictionary GetUserDictionary(string filename)
{
return new DBUserDictionary(filename);
}
}
}
That class is provided using DI to our controller. So to do that you should make it available in ConfigureServices for your app, eg. in Startup
public void ConfigureServices(IServiceCollection services) { services.AddScoped<Keyoti.RapidSpell.IObjectProvider, RapidSpellObjectProvider>(); services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; });
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddApplicationPart(System.Reflection.Assembly.Load(new System.Reflection.AssemblyName("Keyoti.RapidSpellWeb.ASP.NET.Core"))); }
That should then make your DBUserDictionary class be used for the user dictionary.
Now the question arises, how can each user have their own user dictionary? In the DBUserDictionary constructor you can see
public DBUserDictionary(String dictionaryId, int maxNumWords)
the 'dictionaryId' argument is going to be set to the value of the property 'UserDictionaryFile' from the client side.
You can see that this is settable in Javascript on the page being spell checked like
rapidSpell.setParameterValue("default", "UserDictionaryFile", "userId1");
So, what you could do is set that property to the ID of the user or some other unique identifier. Then that identifier will go through to DBUserDictionary and you can use it to organize the user dictionary table by user, perhaps one DB row per user for example.
|