How to use Google Adsense with MVC C# Razor - c#

I am trying to add Google Adsense to my MVC mobile web application. I'd like to implement the Google Adsense Mobile content ad code. The Scripting Language they have is asp 3.0. Is there an MVC helper I can use to display these ads on a MVC C# Razor page? I can't find anything about MVC and displaying web ads online at all. Would love some help, I am totally stuck.
If I use regular Adsense Javascript code. The code doesn't load when I click around the site. Only when I click refresh on the page.

A simple HtmlHelper translated from Adsense ASP sample :
public static class AdsenseHelper
{
public static MvcHtmlString Adsense(this HtmlHelper htmlHelper, string clientKey, string adSlot)
{
var context = htmlHelper.ViewContext.HttpContext;
var request = context.Request;
int googleTime = (DateTime.Now - new DateTime(1970, 1, 1)).Days;
var googleDt = (1000 * googleTime) + Math.Round(1000d * (DateTime.Now - DateTime.Today).Milliseconds);
var googleUserAgent = context.Server.UrlEncode(request.ServerVariables["HTTP_USER_AGENT"]);
var googleScheme = (string.Compare(request.ServerVariables["HTTPS"], "on") == 0) ? "https://" : "http://";
var googleAdUrl =
"http://pagead2.googlesyndication.com/pagead/ads?" +
"client=" + clientKey + // ca-mb-pub-0000000000000000
"&dt=" + googleDt +
"&ip=" + context.Server.UrlEncode(request.ServerVariables["REMOTE_ADDR"]) +
"&markup=xhtml" +
"&output=xhtml" +
"&ref=" + context.Server.UrlEncode(request.ServerVariables["HTTP_REFERER"]) +
"&slotname=" + adSlot + // 0000000000
"&url=" + context.Server.UrlEncode(googleScheme + request.ServerVariables["HTTP_HOST"] + request.ServerVariables["URL"]) +
"&useragent=" + googleUserAgent +
GoogleScreenRes(context.Request) +
GoogleMuid(context.Request) +
GoogleViaAndAccept(context, googleUserAgent);
using (var client = new System.Net.WebClient())
{
string result = client.DownloadString(googleAdUrl);
return new MvcHtmlString(result);
}
}
private static string GoogleColor(string value, int random)
{
var colorArray = value.Split(',');
return colorArray[random % (colorArray.Length)];
}
private static string GoogleScreenRes(HttpRequestBase request)
{
var screenRes = request.ServerVariables["HTTP_UA_PIXELS"];
char delimiter = 'x';
if (string.IsNullOrEmpty(screenRes))
{
screenRes = request.ServerVariables["HTTP_X_UP_DEVCAP_SCREENPIXELS"];
delimiter = ',';
}
if (string.IsNullOrEmpty(screenRes))
{
screenRes = request.ServerVariables["HTTP_X_JPHONE_DISPLAY"];
delimiter = '*';
}
if (screenRes != null)
{
string[] resArray = screenRes.Split(new[] { delimiter }, 2);
if (resArray.Length == 2)
{
return "&u_w=" + resArray[0] + "&u_h=" + resArray[1];
}
}
return string.Empty;
}
private static string GoogleMuid(HttpRequestBase request)
{
var muid = request.ServerVariables["HTTP_X_DCMGUID"];
if (!string.IsNullOrEmpty(muid))
{
return "&muid=" + muid;
}
muid = request.ServerVariables["HTTP_X_UP_SUBNO"];
if (!string.IsNullOrEmpty(muid))
{
return "&muid=" + muid;
}
muid = request.ServerVariables["HTTP_X_JPHONE_UID"];
if (!string.IsNullOrEmpty(muid))
{
return "&muid=" + muid;
}
muid = request.ServerVariables["HTTP_X_EM_UID"];
if (!string.IsNullOrEmpty(muid))
{
return "&muid=" + muid;
}
return string.Empty;
}
private static string GoogleViaAndAccept(HttpContextBase context, string googleUserAgent)
{
if (string.IsNullOrEmpty(googleUserAgent))
return string.Empty;
string googleViaAndAccept = string.Empty;
var via = context.Server.UrlEncode(context.Request.ServerVariables["HTTP_VIA"]);
if (!string.IsNullOrEmpty(via))
{
googleViaAndAccept = "&via=" + via;
}
var accept = context.Server.UrlEncode(context.Request.ServerVariables["HTTP_ACCEPT"]);
if (!string.IsNullOrEmpty(accept))
{
googleViaAndAccept = googleViaAndAccept + "&accept=" + accept;
}
return googleViaAndAccept;
}
}
This helper does not work with desktop browsers. But can be bypassed by changing the useragent as Opera Mini.
Like Google says :
AdSense for Mobile Content is only for use on websites designed with older feature phones in mind. As fully web-capable smartphones become more and more common, we recommend that you use AdSense for Content for all of your Content Ads needs.

Related

txtbox string and innerText/innerHTML (HTMLAGILITYPACK) are returning a false comparison

I have pulled some information from the internet using HTMLAGilityPack. No problem.
I then pass the innerHTML through a method I took from stackoverflow (this is to remove mark ups etc and make it plaintext).
I then call a boolean to determine if the new output is the same as a txtInput on the form. It is returning false even though they are the same?
I know nothing about unicode, UT-8, Cry, character bytes etc.. Though i'm assuming the binary are different? even though they appear the same? How can I get around this problem.
This is the string in the input box, the same one it pulls from HTMLAGilitypack
"When I Grow Up (feat. Lauren Ward & Bailey Ryon)"
This is the 2 outputs side by side.
As you can see from the pictures, face value they look exactly the same. Yet it returns false. Please how can I fix this?
Here is my code:
This checks if the values are different and always returns false.
private bool CheckText(string node)
{
string value = HtmlToPlainText(txtSong.Text);
if (value == node)
return true;
else
return false;
}
This is the method that actually pulls the data, If it matches it will open the page, if it doesn't it retry.
private void pullTable(int pageNum, string keyWord, int resultStart)
{
int countCheck = 0;
while (countCheck == 0)
{
System.Threading.Thread.Sleep(3000);
HtmlWeb web = new HtmlWeb();
string amazon = "https://www.amazon.co.uk/s/ref=nb_sb_noss_2?url=search-alias%3Ddigital-music&page=" + pageNum + "";
if (txtSong.Text != "")
{
string temp = txtSong.Text.Replace("(", "%28");
temp = temp.Replace(")", "%26");
amazon = amazon + "&field-keywords=" + temp;
}
if (txtArtist.Text != "")
{
string temp = txtArtist.Text.Replace("(", "%28");
temp = temp.Replace(")", "%26");
amazon = amazon + "&field-author=" + temp;
}
if (radioArtistAZ.Checked)
amazon = amazon + "&sort=artist-album-asc-rank";
else if (radioArtistZA.Checked)
amazon = amazon + "&sort=artist-album-desc-rank";
else if (radioSongAZ.Checked)
amazon = amazon + "&sort=title-asc-rank";
else if (radioSongZA.Checked)
amazon = amazon + "&sort=title-desc-rank";
{
}
var doc = web.Load(amazon);
System.Threading.Thread.Sleep(200);
var nodes = doc.DocumentNode.SelectNodes("//body");
try
{
nodes = doc.DocumentNode.SelectNodes("//tr[starts-with(#id, 'result_')]/td[2]/div/a");
}
catch (Exception)
{
}
try
{
for (int i = 0; i < 50; i++)
{
// string tempValue = nodes[i].InnerHtml.Replace("&", "&");
var plainText = HtmlToPlainText(nodes[i].InnerText);
if (CheckText(plainText))
{
AppendTextBox("Opening on page " + pageNum);
System.Diagnostics.Process.Start(amazon);
found = 1;
countCheck = 1;
return;
}
else
{
}
}
countCheck = 1;
AppendTextBox("Not found on page " + pageNum);
}
catch (Exception)
{
AppendTextBox("error on page " + pageNum);
System.Threading.Thread.Sleep(1500);
}
}
}

C# page keeps sending old data

So I hava a page where the user gives data for the app to send it to a database.
When the user clicks on next the app navigates to the next page. But when the user goes back and edits the data the app still saves the old data from the first input to the database.
For example:
Name : Jon Do
The user made a mistake and goes to the previous pageL
Name : John Doe
The user clicks next and the data gets saved to the database. But except of saving the new data "John Doe" it sends the old data, "Jon Do". This, ofcourse, should not happen. I have no clue why this happens.
Here is my C# code of the page where the user should give his/her data
private void btnNext_Click(object sender, RoutedEventArgs e)
{
if (ckbGegevens.IsChecked == false)
{
try
{
dt.saveData = true;
dt.bedrijfsNaam = txxBvName.Text;
dt.contactPersoon = txxContPersn.Text;
dt.telNummer = Convert.ToInt32(txxTelNr.Text);
dt.eMail = txxEMail.Text;
dt.land = txxLand.Text;
dt.plaats = txxPlaats.Text;
dt.postcode = txxPostCode.Text;
postToJson.post("bvg");
this.NavigationService.Navigate(new Doelen());
}
catch (Exception)
{
MessageBox.Show("Er ontbreken gegevens!\nOf u heeft ongeldige gegevens ingevuld!");
}
}
else
{
try {
dt.bedrijfsNaam = txxBvName.Text;
dt.contactPersoon = txxContPersn.Text;
dt.telNummer = Convert.ToInt32(txxTelNr.Text);
dt.eMail = txxEMail.Text;
dt.land = txxLand.Text;
dt.plaats = txxPlaats.Text;
dt.postcode = txxPostCode.Text;
dt.saveData = false;
MessageBox.Show("Uw gegevens worden niet opgeslagen.\nVink voor optimaal gebruik deze functie aan.");
this.NavigationService.Navigate(new Doelen());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
This is how I save it to the database:
static string bedrijfsNaam = dt.bedrijfsNaam;
static string ContPers = dt.contactPersoon;
static int TelNum = dt.telNummer;
static string email = dt.eMail;
static string Land = dt.land;
static string Plaats = dt.plaats;
static string PostCode = dt.postcode;
static string json;
static string b64encode;
public postToJson(string reqCat)
{
}
public static void post(string reqCat)
{
if (reqCat == "bvg")
{
json = "{\"bedrijfsNaam\":\"" + bedrijfsNaam + "\"," +
"\"ContPers\":\"" + ContPers + "\"," +
"\"TelNum\":\"" + TelNum + "\"," +
"\"email\":\"" + email + "\"," +
"\"Land\":\"" + Land + "\"," +
"\"Plaats\":\"" + Plaats + "\"," +
"\"PostCode\":\"" + PostCode + "\"}";
var b64bytes = System.Text.Encoding.UTF8.GetBytes(json);
b64encode = System.Convert.ToBase64String(b64bytes);
var data = new NameValueCollection();
data["b64string"] = b64encode;
data["filename"] = dt.bedrijfsNaam;
using (WebClient client = new WebClient())
{
var sendB64 = client.UploadValues("http://" + ConfigurationManager.AppSettings["scripturi"].ToString() + "SalesKicker.php", "POST", data);
}
}
}
The problem isn't in the PHP script so I don't have to post that script. I know this because I printed out the result of the JSON. Which always has the data from the first input.
Can someone please tell me what is going on here?
The assignments seem to be done in the declaration of the static class, thereby they will only happen once and you don't know when. Therefore you should put these in a separate method:
static string bedrijfsNaam = dt.bedrijfsNaam;
static string ContPers = dt.contactPersoon;
static int TelNum = dt.telNummer;
static string email = dt.eMail;
static string Land = dt.land;
static string Plaats = dt.plaats;
static string PostCode = dt.postcode;
And then call that method in the post method.
E.g.
private static void updateData() {
bedrijfsNaam = dt.bedrijfsNaam;
ContPers = dt.contactPersoon;
TelNum = dt.telNummer;
email = dt.eMail;
Land = dt.land;
Plaats = dt.plaats;
PostCode = dt.postcode;
}

wpf webbrowser uri containing other language such as Korean

i have a trouble when i use MyWebBrowser.Source = new Uri(uri);
i want to add Korean to uri. but when i do it, i can see broken characters which was from Korean. i searched for solution, but i couldn't understand the way. someone instructs the way using encode/decode.. but, i don't know how to apply it to my code.
please help me
.
<Grid Background="White"><WebBrowser Name="MyWebBrowser" /></Grid>
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
change_room();
}
private void change_room()
{
string room_name = "example";
string nick = "한글";// 한글 means Korean.
string uri = "http://" + room_name + ".com/chat?nick=" + nick ;
try
{
MyWebBrowser.Source = new Uri(uri);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
string uri = "http://" + room_name + ".server.ohcs.uu.gl/chat?nick=" + HttpUtility.UrlEncode(nick,System.Text.Encoding.GetEncoding("euc-kr")`) + "&text=&sessid=" + room_name;
above code can't make Korean correct.
You should use the HttpUtility.UrlEncode method on strings that are from user input and strings that contain characters that'd break the URL/not get through correctly (ampersand, foreign chars, etc). This way, it'll be safe for use in a URL.
string uri = "http://" + HttpUtility.UrlEncode(room_name) + ".com/chat?nick=" + HttpUtility.UrlEncode(nick, System.Text.Encoding.GetEncoding("euc-kr"));
The HttpUtility class can be found in the assembly System.Web.dll. If there's an error relating to the namespace not being found, make sure to add the reference to System.Web.dll using the Add References dialog.
i add more explanations about solution i found.
this is xaml code <.WebBrowser x:Name="webBrowser" /.>
below is cs code
public room1()
{
string nick = "한글";
webBrowser.Navigate("http:/freechat.esy.es/minichat?chat=room1&nick=" + nick );
}
above codes are inappropriate because "한글" is not a regular letter i think.
UriBuilder builder = new UriBuilder("http://freechat.esy.es/minichat?chat=room1&nick=한글");
string url = builder.ToString();
WebBrowser web = new WebBrowser();
web.Navigate(url);
UriBuilder convert unregualr letters containing "한글"[string url] to regualr letters which can be accepted to web.
input letters : [http://freechat.esy.es/minichat?chat=room1&nick=한글]
translated letters by UriBuilder :
[http:/freechat.esy.es/minichat?chat=room1&nick=%ED%95%9C%EA%B8%80]
I found the answer. I'm currently using the following code and it now works fine.
string make_uri(string uri)
{
UriBuilder ub = new UriBuilder(uri);
string ubS = ub.ToString();
return ubS;
}
string send_uri { get; set; }
private void NavigateTo()
{
int cs = combo1.SelectedIndex;
if (DN == "Your Nick")
{
if (cs == 0) send_uri = ("http://freechat.esy.es/minichat?chat=room1" + mode + key);
else if (cs == 1) send_uri = ("http://freechat.esy.es/minichat?chat=chataa" + mode + key);
else if (cs == 2) send_uri = ("http://freechat.esy.es/minichat?chat=room2" + mode + key);
}
else
{
if (cs == 0) send_uri = (make_uri("http://freechat.esy.es/minichat?chat=room1&nick=" + DN + mode + key));
else if (cs == 1) send_uri = (make_uri("http://freechat.esy.es/minichat?chat=chataa&nick=" + DN + mode + key));
else if (cs == 2) send_uri = (make_uri("http://freechat.esy.es/minichat?chat=room2&nick=" + DN + mode + key));
}
webBrowser.Navigate(send_uri);
}

programatically create iis 6.0 website and application pool with specified .net version

I need to create a new website in iis 6.0 (Windows server 2003 r2 sp2) and create a new virtual directory with .net framework 4.0 and assign it to created website.
here is my code :
public static int CreateWebSite(string webSiteName, string PhysicalPath, string PortNumber, string HostHeader, string DefaultDoc, string appPoolName, out string errorMessage)
{
errorMessage = string.Empty;
try
{
DirectoryEntry root = new DirectoryEntry("IIS://localhost/W3SVC");
// Find unused ID value for new web site
int siteID = 1;
foreach (DirectoryEntry e in root.Children)
{
if (e.SchemaClassName == "IIsWebServer")
{
int ID = Convert.ToInt32(e.Name);
if (ID >= siteID)
{
siteID = ID + 1;
}
}
}
DirectoryEntry site = (DirectoryEntry)root.Invoke("Create", "IIsWebServer", siteID);
site.Invoke("Put", "ServerComment", webSiteName);
site.Invoke("Put", "KeyType", "IIsWebServer");
site.Invoke("Put", "ServerBindings", ":" + PortNumber + ":" + HostHeader);
site.Invoke("Put", "ServerState", 2);
site.Invoke("Put", "FrontPageWeb", 1);
site.Invoke("Put", "DefaultDoc", DefaultDoc);
site.Invoke("Put", "ServerAutoStart", 1);
site.Invoke("Put", "ServerSize", 1);
site.Invoke("SetInfo");
DirectoryEntry siteVDir = site.Children.Add("Root", "IISWebVirtualDir");
if (appPoolName != "")
{
object[] param = { 0, appPoolName, true };
siteVDir.Invoke("AppCreate3", param);
}
siteVDir.Properties["AppIsolated"][0] = 2;
siteVDir.Properties["Path"][0] = PhysicalPath;
siteVDir.Properties["AccessFlags"][0] = 513;
siteVDir.Properties["AspEnableParentPaths"][0] = true;
siteVDir.Properties["AppFriendlyName"][0] = webSiteName;
siteVDir.Properties["FrontPageWeb"][0] = 1;
siteVDir.Properties["AppRoot"][0] = "LM/W3SVC/" + siteID + "/Root";
siteVDir.Properties["AppFriendlyName"][0] = "Root";
siteVDir.Properties["AspSessionTimeout"][0] = "60";
siteVDir.Properties["AuthFlags"].Value = 4;//integrity windows Authentication checked
siteVDir.Properties["AuthAnonymous"][0] = true;//Anonymouse uncheck
siteVDir.Properties["HttpErrors"].Add("401,1,FILE," + PhysicalPath + "/Lib/CustomError/SSOLoginError.htm");
siteVDir.Properties["HttpErrors"].Add("401,2,FILE," + PhysicalPath + "/Lib/CustomError/SSOLoginError.htm");
siteVDir.Properties["HttpErrors"].Add("401,3,FILE," + PhysicalPath + "/Lib/CustomError/SSOLoginError.htm");
siteVDir.Properties["HttpErrors"].Add("401,4,FILE," + PhysicalPath + "/Lib/CustomError/SSOLoginError.htm");
siteVDir.Properties["HttpErrors"].Add("401,5,FILE," + PhysicalPath + "/Lib/CustomError/SSOLoginError.htm");
siteVDir.Properties["HttpErrors"].Add("401,7,FILE," + PhysicalPath + "/Lib/CustomError/SSOLoginError.htm");
//For SSO, Set special settings for WinLogin.aspx page -- This has beed added after version 8.1.1001
DirectoryEntry deLoginDir;
deLoginDir = siteVDir.Children.Add("WinLogin.aspx", siteVDir.SchemaClassName);
deLoginDir.Properties["AuthAnonymous"][0] = false;//Anonymouse uncheck
deLoginDir.Properties["AuthFlags"].Value = 4;//integrity windows Authentication checked
deLoginDir.CommitChanges();
////////////////////////////////////////////
siteVDir.CommitChanges();
siteVDir.Invoke("AppDelete");
siteVDir.Invoke("AppCreate", true);
siteVDir.Invoke("AppEnable");
site.CommitChanges();
#region AssignApplicationPool
DirectoryEntry vDir = new DirectoryEntry("IIS://localhost/W3SVC/" + siteID.ToString() + "/Root");
string className = vDir.SchemaClassName.ToString();
if (className.EndsWith("VirtualDir"))
{
object[] param = { 0, appPoolName, true };
vDir.Invoke("AppCreate3", param);
vDir.Properties["AppIsolated"][0] = "2";
vDir.CommitChanges();
}
else
{
return -1;
}
if (Environment.OSVersion.Version.Major < 6)
{
try
{
const string aspNetV1 = "1.0.3705";
const string aspNetV11 = "1.1.4322";
const string aspNetV2 = "2.0.50727";
const string aspNetV4 = "4.0.30319";
const string targetAspNetVersion = aspNetV4;
//loop through the script maps
for (var i = 0; i < siteVDir.Properties["ScriptMaps"].Count; i++)
{
//replace the versions if they exists
siteVDir.Properties["ScriptMaps"][i] =
siteVDir.Properties["ScriptMaps"][i].ToString().Replace(aspNetV1, targetAspNetVersion);
siteVDir.Properties["ScriptMaps"][i] =
siteVDir.Properties["ScriptMaps"][i].ToString().Replace(aspNetV11, targetAspNetVersion);
siteVDir.Properties["ScriptMaps"][i] =
siteVDir.Properties["ScriptMaps"][i].ToString().Replace(aspNetV2, targetAspNetVersion);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
errorMessage = ex.Message + Environment.NewLine + ex.StackTrace;
}
}
else
{
string appPoolPath = #"IIS://localhost/W3SVC/AppPools/" + appPoolName;
try
{
var appPoolEntry = new DirectoryEntry(appPoolPath);
appPoolEntry.Properties["managedRuntimeVersion"].Value = "v4.0";
appPoolEntry.Invoke("SetInfo", null);
appPoolEntry.CommitChanges();
appPoolEntry.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
errorMessage = ex.Message + Environment.NewLine + ex.StackTrace;
}
siteVDir.CommitChanges();
siteVDir.Close();
}
#endregion
return siteID;
}
catch
{
return -1;
}
}
This code should work fine in IIS 6.0 (Windows 2003) and IIS 7.5+ (Windows 7 and Windows 2008).
in windows 7 and 2008 every thing looks fine! but in windows 2003 I have some problems:
Asp.net version of website does not change to v4
Application Pool does not seems correct and its node in inetmgr only have one node with name Root not the name of website
in the properties window of website -> home directory tab, application name is empty!
what is wrong with my code?
thanks in advance
DirectoryEntry sited = new DirectoryEntry(string.Format("IIS://localhost/w3svc/{0}/Root", websiteID.ToString()));
sited.Properties["AccessRead"].Add(true);
PropertyValueCollection testScriptMap = sited.Properties["ScriptMaps"];
object[] allValues = (object[])testScriptMap.Value;
object[] newValues = new object[allValues.Length];
string oldVersion = "v1.1.4322";
string newVersion = "v2.0.50727";
//... etc to 4.0.30319 .....
for (int i = 0; i < allValues.Length; i++)
{
if (allValues[i] is string)
{
string temp = allValues[i] as string;
if (temp.Contains(oldVersion))
{
newValues[i] = temp.Replace(oldVersion, newVersion);
}
else
{
newValues[i] = allValues[i];
}
}
else
{
newValues[i] = allValues[i];
}
}
testScriptMap.Value = newValues;
sited.CommitChanges();

EWS + Exchange 2007: Retrieve inline images

Working in C# with the EWS Managed API, we're having trouble efficiently retrieving the images stored as inline attachments.
The endpoint is to show an email with inline images as a fully formed html page in a panel. The code we currently us:
string sHTMLCOntent = item.Body;
FileAttachment[] attachments = null;
if (item.Attachments.Count != 0)
{
attachments = new FileAttachment[item.Attachments.Count];
for (int i = 0; i < item.Attachments.Count; i++)
{
string sType = item.Attachments[i].ContentType.ToLower();
if (sType.Contains("image"))
{
attachments[i] = (FileAttachment)item.Attachments[i];
string sID = attachments[i].ContentId;
sType = sType.Replace("image/", "");
string sFilename = sID + "." + sType;
string sPathPlusFilename = Directory.GetCurrentDirectory() + "\\" + sFilename;
attachments[i].Load(sFilename);
string oldString = "cid:" + sID;
sHTMLCOntent = sHTMLCOntent.Replace(oldString, sPathPlusFilename);
}
}
}
(sourced: http://social.technet.microsoft.com/Forums/en-US/exchangesvrdevelopment/thread/ad10283a-ea04-4b15-b20a-40cbd9c95b57)
.. this is not very efficient though and is slowing down the responsiveness of our web app. Does anyone have a better solution for this problem? We are using Exchange 2007 SP1, so the IsInline property wont work as its Exchange 2010 only.
I build an index of your "cid:"s first:
private const string CidPattern = "cid:";
private static HashSet<int> BuildCidIndex(string html)
{
var index = new HashSet<int>();
var pos = html.IndexOf(CidPattern, 0);
while (pos > 0)
{
var start = pos + CidPattern.Length;
index.Add(start);
pos = html.IndexOf(CidPattern, start);
}
return index;
}
Then you need a replace function that replaces the cids based on your index
private static void AdjustIndex(HashSet<int> index, int oldPos, int byHowMuch)
{
var oldIndex = new List<int>(index);
index.Clear();
foreach (var pos in oldIndex)
{
if (pos < oldPos)
index.Add(pos);
else
index.Add(pos + byHowMuch);
}
}
private static bool ReplaceCid(HashSet<int> index, ref string html, string cid, string path)
{
var posToRemove = -1;
foreach (var pos in index)
{
if (pos + cid.Length < html.Length && html.Substring(pos, cid.Length) == cid)
{
var sb = new StringBuilder();
sb.Append(html.Substring(0, pos-CidPattern.Length));
sb.Append(path);
sb.Append(html.Substring(pos + cid.Length));
html = sb.ToString();
posToRemove = pos;
break;
}
}
if (posToRemove < 0)
return false;
index.Remove(posToRemove);
AdjustIndex(index, posToRemove, path.Length - (CidPattern.Length + cid.Length));
return true;
}
so now, you can check your attachments
FileAttachment[] attachments = null;
var index = BuildCidIndex(sHTMLCOntent);
if (index.Count > 0 && item.Attachments.Count > 0)
{
var basePath = Directory.GetCurrentDirectory();
attachments = new FileAttachment[item.Attachments.Count];
for (var i = 0; i < item.Attachments.Count; ++i)
{
var type = item.Attachments[i].ContentType.ToLower();
if (!type.StartsWith("image/")) continue;
type = type.Replace("image/", "");
var attachment = (FileAttachment)item.Attachments[i];
var cid = attachment.ContentId;
var filename = cid + "." + type;
var path = Path.Combine(basePath, filename);
if(ReplaceCid(index, ref sHTMLCOntent, cid, path))
{
// only load images when they have been found
attachment.Load(path);
attachments[i] = attachment;
}
}
}
Additional to that: instead of calling attachment.Load right away, and pass the path to the image directly, you could link to another script, where you pass the cid as a parameter and then check back with the exchange for that image; then the process of loading the image from exchange does not block the html cid replacement and could lead to loading the page faster, since the html can send to the browser sooner.
PS: Code is not tested, just so you get the idea!
EDIT
Added the missing AdjustIndex function.
EDIT 2
Fixed small bug in AdjustIndex

Categories

Resources