MVC Ajax Browser History

Когда вы используете Ajax вызовы то после того как вы воспользуетесь кнопкой «назад» в браузере – то скорее всего получите неприятную ошибку, связанную с тем что барузер запомнил путь для вызова ajax.

[HttpPost]
public ActionResult AjaxResult()
{
if (this.Request.IsAjaxRequest()) return PartialView("AjaxTestView");
return View("TestView");
}

MVC AJAX – с чего начать

Для начала нам нужны скрипты:

<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>

 Для того чтобы это все заработало нам нужна Ajax форма:

@using (Ajax.BeginForm("ActionName", new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "ajaxDiv",
}))
{           
<div id="ajaxDiv">
@{Html.RenderPartial("~/Views/News/Control.cshtml", new Model.TestModel(true));}
</div>
}

Немного подробнее. Я использую имя действия – которое мне возвращает сформированный Partial View. В AjaxOption я указываю HttpMetod, InsertionMode – это способ вставки, можно заменить, добавить в начало, и в конец блока, UpdateTargetId – это имя контейнера в котором должны быть отображены данные. В самом теле формы нужно разместить контрол который будет вызывать submit формы. В моем случае я перегружаю полностью весь контрол, методами вызванными из самого контрола, по этому я его и разместил в форме.
Можно сделать и так:

 

@using (Ajax.BeginForm("GetData", new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "ajaxDiv",
}))
{           
<input type="submit" value="Загрузить" />
}
<div id="ajaxDiv">
@{Html.RenderPartial("~/Views/News/Control.cshtml", new Model.TestModel(true));}
</div>

 В контроллере для Ajax у меня есть Action:

[HttpPost]
public ActionResult GetData()
{
Model.TestModel model = new Model.TestModel();
return PartialView ("~/Views/News/Control.cshtml", model);
}

В моем случае он возвращает Partial View который и записывается в div – "ajaxDiv"

 

А что делать если нужно передавать параметры? Для этого нужно указать их в параметре routeValues:

@Ajax.ActionLink(, "MonuthChange", 
new { Param1 = Model.Param1, Param2 = Model.Param2 }, new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "calendar"
}, new { @class = "active" })

 А в контроллере:

public ActionResult GetData(string Param1, int Param2)
{
Model.TestModel model = new Model.TestModel();
return PartialView ("~/Views/News/Control.cshtml", model);
}

 Интересный момент, чтобы контролы могли отправить Ajax форму или запрос, нужно использовать котролы не из @Html а из @Ajax.

MVC как добавить к контролам Html свойства через htmlAttributes

Для этого нужно сделать новый объект и задать нужные атрибуты через htmlAttributes, главное перед именем атрибута поставить @.

Если есть routeValues:

@Html.ActionLink("linkText","ActionName", 
new {RouteValues = 1},new {@class = "Active"})

 

А если routeValues не нужны можно сделать так:

@Html.ActionLink("linkText","ActionName", 
FormMethod.Post,new {@class = "Active"})

Счетчики производительности PerformanceCounter в C#

Важное замечание, чтобы счетчики давали правдивые результаты их нужно объявить один раз и после этого к ним обращаться скажем по таймеру. Если вы будете постоянно создавать заново счетчики то они будут возвращать значение – 0. Так как им нужно время для сбора данных.
Я приведу пример четырех счетчиков: Процессора, памяти, файла подкачки и сети.

 

public partial class MainWindow : Window
{
PerformanceCounter cpuUsage;
PerformanceCounter memUsage;
PerformanceCounter pageUsage;
List<PerformanceCounter> netUsage = null;
System.Timers.Timer tmr;
public MainWindow()
{
InitializeComponent();
cpuUsage = new PerformanceCounter("Processor", "% Processor Time", "_Total");
memUsage = new PerformanceCounter("Memory", "Available MBytes");
netUsage = GetNetCounters();
pageUsage = new PerformanceCounter("Paging File", "% Usage", "_Total");
tmr = new System.Timers.Timer();
tmr.Elapsed += tmr_Elapsed;
tmr.Interval = 1000;
tmr.Start();
}
void tmr_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Dispatcher.BeginInvoke(new ThreadStart(delegate
{
cont.Children.Clear();
cont.Children.Add(new Label() { Content = "Processor " + cpuUsage.NextValue()+ " %" });
cont.Children.Add(new Label() { Content = "memory free  " + memUsage.NextValue() +" mb"});
//добавить System.Management
string Query = "SELECT MaxCapacity FROM Win32_PhysicalMemoryArray";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(Query);
foreach (ManagementObject WniPART in searcher.Get())
{
UInt32 SizeinKB = Convert.ToUInt32(WniPART.Properties["MaxCapacity"].Value);
UInt32 SizeinMB = SizeinKB / 1024;
UInt32 SizeinGB = SizeinMB / 1024;
cont.Children.Add(new Label() { Content = "memory " + ((memUsage.NextValue() / SizeinMB)*100)+"% used" });
cont.Children.Add(new Label() { Content = "memory used " + (SizeinMB - memUsage.NextValue())});
cont.Children.Add(new Label() { Content = "page used " + pageUsage.NextValue() });
foreach (var item in netUsage)
{
cont.Children.Add(new Label() { Content = "network  " + item.NextValue() });
}
}
}));
}
private List<PerformanceCounter> GetNetCounters()
{
string filter = "MS TCP Loopback interface";
List<string> nics = new List<string>();
PerformanceCounterCategory category = new PerformanceCounterCategory("Network Interface", System.Environment.MachineName);
if (category.GetInstanceNames() != null)
{
foreach (string nic in category.GetInstanceNames())
{
if (!nic.Equals(filter, StringComparison.InvariantCultureIgnoreCase))
{ nics.Add(nic); }
}
List<PerformanceCounter> nicCounters = new List<PerformanceCounter>();
foreach (string nicInstance in nics)
{
nicCounters.Add(new PerformanceCounter("Network Interface", "Bytes Total/sec", nicInstance, System.Environment.MachineName));
}
return nicCounters;
}
else
{
return null;
}
}
}

Счетчики использую стандартные системные счетчики с которых они и берут данные.

Подробнее о счетчиках:

http://msdn.microsoft.com/en-us/library/ms998581.aspx

http://technet.microsoft.com/en-us/library/cc938593.aspx

http://blogs.msdn.com...setting-up-performance-counters-in-your-web-and-worker-roles.aspx

Увеличение размеров пакетов в WCF Service.

Иногда бывает так что ваш ответ от сервера слишком большой и клиент говорит что превышен максимальный размер сообщение в 65536.
В таком случае в app.config (или web.config) клиента нужно указать максимальный размер сообщения которое может получить клиент, например - maxReceivedMessageSize="2147483647"  - это примерно 2GB. Это максимальное значение.
 

<bindings>
<basicHttpBinding>
<binding name="userHttp" maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
<binding name="StreamedBinding" transferMode="Streamed" maxReceivedMessageSize="2147483647" />
</basicHttpBinding>
</bindings>

Так же стоит упомянть о таймаутах:

 

<binding name="BasicHttpBinding_IReportService" 
closeTimeout="00:10:00" 
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" maxReceivedMessageSize="2147483647">
</binding>

closeTimeout, openTimeout, receiveTimeout, sendTimeout – задают время за которые должна выполниться операция. Если вы получаете и отправляете большие данные то возможно вам это понадобиться. По умолчанию значение 00:01:00 – что значит одна минута.

Отладка WCF сервисов

Если ваш WCF сервис не работает, и вы мне можете запустить его из отладчика Visual Studio, а в ошибке клиента приходит что-то типа «включите includeExceptionDetailInFaults»
Тогда нужно вклчить его, указав параметр includeExceptionDetailInFaults="true". Для этого в web.config сервера нужно найти секцию behaviors -> serviceBehaviors и включить там эту опцию:

<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>

Вот примерно так как указано в примере, в первом случае у меня includeExceptionDetailInFaults выключена, а во втором включена. После этого в отладчике клиента вы получите информацию об ошибке.

Visual studio 2012 – как сделать package web сайта

Если в Visual Studio 2010 для этого был пункт в контекстном меню "Build Deployment Package", то в Visual Studio 2012 это нет.
Для того чтобы упаковать свой сайт и подготовить его к публикации нужно:
1. Нажать правкой кнопкой мыши на проекте и выбрать Publish.
2. В появившемся окне создать новый профиль для вашего пакета.
3. Во втором пункте "Connection" выбрать "Web Deploy Package" и указать папку куда будет сохранен сформированный пакет.
4.  Дальше выбрать конфигурацию и нажать Publish.
5. Ну и собственно все :)

События в C# или как сделать свой Event

Events – это события которые вызывает ваш класс, информируя тем самым своих подписчиков о том что произошло какое-то либо событие.
Если вам нужно передавать какие-либо параметры то кроме самого event’a вам нужно реализовать свой класс EventArgs через который вы и будете передавать параметры.

//создаем своей EventArgs.
public class TestEventArgs: EventArgs
{
public TestEventArgs(string s) { Text = s; }
public String Text {get; set;} 
}
public class Publisher
{
// создали делегат
public delegate void TestEventHandler(object sender, TestEventArgs e);
// объявили event
public event TestEventHandler TestEvent;
// функция вызова делегата
protected virtual void DoSomethingEvent()
{
if (TestEvent != null)
TestEvent(this, new TestEventArgs("Hi"));
}
}

 или

public class Publisher
{
	// объявили event
	public event EventHandler<TestEventArgs> TestEvent;
	// функция вызова делегата           
	protected virtual void DoSomethingEvent()
	{
		var handler = Interlocked.CompareExchange(ref this.TestEvent, null, null);

		if (handler != null)
		{
			handler(this, new TestEventArgs("Hi"));
		}
	}
}

Стоит упомянуть что  эту проверку надо делать обязательно. Она означает что у вас есть подписчики и есть кому отправлять событие.

if (TestEvent != null)
TestEvent(this, new TestEventArgs("Hi"));

А еще лучше вот так:

var handler = Interlocked.CompareExchange(ref this.TestEvent, null, null);

                if (handler != null)
                {
                    handler(this, new TestEventArgs("Hi"));
                }

Если проверки не сделать, то у вас может образоваться исключение.

Ну и в завершении, подписываться на события:

Test.TestEvent += new TestEventHandler();

Или так:

var handler = Volatile.Read(ref this.TestEvent);

                if (handler != null)
                {
                    handler(this, new TestEventArgs("Hi"));
                }

Или вот так, для C# 6:

Volatile.Read(ref this.TestEvent)?.Invoke(this, new TestEventArgs("Hi"));;

Или вот так, для C# 6:

Interlocked.CompareExchange(ref this.TestEvent, null, null)?.Invoke(this, new TestEventArgs("Hi"));

Отписывается от события:

Test.TestEvent -= new TestEventHandler();


Что почитать:
http://msdn.microsoft.com/ru-ru/library/8627sbea.aspx

https://habrahabr.ru/post/272571/

https://habrahabr.ru/post/240385/

Дата центры и размеры виртуальных машин в Azure

Виртуальные машины:

Размер Процессор Память Локальное хранилище
Extra Small         1.0 ГГц     768 Мбайт       20 Гбайт
Small      1.6 ГГц 1.75 Гбайт   225 Гбайт
Medium 2 х 1.6 ГГц   3.5 Гбайт   490 Гбайт
Large 4 х 1.6 ГГц      7 Гбайт 1000 Гбайт
Extra Large 8 х 1.6 ГГц    14 Гбайт 2040 Гбайт

Регионы дата центров:
West US
East US
East Asia
Southeast Asia
North Europe
West Europe

Тест производительности SQL Azure vs SQL Server vs Table Storage

В процессе подбора оптимального хранилища я прочитал много статей в которых говорилось что SQL Azure работает значительно медленнее чем Table Storage и медленнее чем SQL Server. Но никаких цифр я не нашёл, по этому решил все таки проверить с какой скоростью на самом деле работают SQL Azure и Table Storage, и для сравнения я взял SQL Server 2008 R2 Express.
Результаты оказались достаточно интересные, для теста я взял простой класс, для Table Storage:

public class lTEST : TableServiceEntity
{
public lTEST()
: base()
{
}
public lTEST(string partitionKey, string rowKey)
: base(partitionKey, rowKey)
{
}
public int TEST0 { get; set; }
public string TEST1 { get; set; }
public string TEST2 { get; set; }
public string TEST3 { get; set; }
public string TEST4 { get; set; }
public double TEST5 { get; set; }
public DateTime TEST6 { get; set; }
public int TEST7 { get; set; }
public double TEST8 { get; set; }
public bool TEST9 { get; set; }
public string TEST10 { get; set; }
}


А для SQL:

create table sqlTEST
(
TEST0 int IDENTITY(1,1) NOT NULL PRIMARY KEY,
TEST1 nvarchar(400),
TEST2 nvarchar(400),
TEST3 ntext,
TEST4 ntext,
TEST5 decimal,
TEST6 datetime,
TEST7 int,
TEST8 decimal,
TEST9 bit,
TEST10 ntext,
)

 

Заполнение для Table:

for (int i = 0; i < 1000; i++)
{
lTEST ltestItem = new lTEST("testpk",i.ToString());
ltestItem.TEST0 = 0;
ltestItem.TEST1 = new string('A', 100);
ltestItem.TEST2 = new string('B', 100);
ltestItem.TEST3 = new string('C', 100);
ltestItem.TEST4 = new string('D', 100);
ltestItem.TEST5 = 50;
ltestItem.TEST6 = System.DateTime.Now;
ltestItem.TEST7 = 50;
ltestItem.TEST8 = 432.32;
ltestItem.TEST9 = true;
ltestItem.TEST10 = new string('D', 100);
TableHelper.InsertEntity("test", ltestItem);
}

 

Для SQL:
 

for (int i = 0; i < 1000; i++)
{
SqlTEST ltestItem = new SqlTEST();
// ltestItem.TEST0 = 0;
ltestItem.TEST1 = new string('A', 100);
ltestItem.TEST2 = new string('B', 100);
ltestItem.TEST3 = new string('C', 100);
ltestItem.TEST4 = new string('D', 100);
ltestItem.TEST5 = 50;
ltestItem.TEST6 = System.DateTime.Now;
ltestItem.TEST7 = 50;
ltestItem.TEST8 = 432.32;
ltestItem.TEST9 = true;
ltestItem.TEST10 = new string('D', 100);
sem.Add(ltestItem);
}
sem.SaveChanges();


 

Стоит сказать что для доступа к базам я использую Telerik Open Access.
Тестировал я таким образом, поочередно в цикле for добавлял записи в Table Storage, SQL Azure и SQL Server.
После создание всех записей, я их вычитывал из хранилищ.
По заверении, я удалял все записи из баз данных.
По чему у SQL серверов по 2 записи времени? В первой записи я делаю SaveChanges() сразу после добавления элемента, во втором – после выхода из цикла. Для 10000 я делаю сохранение данных в SQL каждые 1000 элементов, иначе сервер закрывает подключение из за превышение интервала ожидания. Все это я делал в одном потоке, поочередно.


Перейдем к результатам:

Хранилище

Кол-во записей

Время записи

Время чтения

Время удаления

Table Storage

10

    963 ms.

 1 871 ms.

 

SQL Azure

10

  3 205 ms.

   252 ms.

   367 ms.

SQL Server 2008 R2 Express

10

  1 082 ms.

   402 ms.

   167 ms.

 

 

 

 

 

Table Storage

100

  5 619 ms.

 2 564 ms.

 

SQL Azure

100

 37 479 ms.

  9 138 ms.

 4 531 ms.

 2 312 ms.

SQL Server 2008 R2 Express

100

 10 295 ms.

  5 286 ms.

   573 ms.

   569 ms.

 

 

 

 

 

Table Storage

1000

 65 177 ms.

 9 718 ms.

 

SQL Azure

1000

274 685 ms.

109 021 ms.

10 233 ms.

11 649 ms.

SQL Server 2008 R2 Express

1000

105 843 ms.

 56 938 ms.

 1 528 ms.

 4 114 ms.

 

 

 

 

 

Table Storage

10000

576 184 ms.

46 790 ms.

 

SQL Azure

10000

951 458 ms.

44 058 ms.

 

SQL Server 2008 R2 Express

10000

551 167 ms.

 9 333 ms.

 

 

 

 

 

 

Итого:

 

 

 

 

Table Storage

В среднем

  58,32 ms.

  5.49 ms.

 

SQL Azure

В среднем

  96,02 ms.

  5.31 ms.

 

SQL Server 2008 R2 Express

В среднем

  55,30 ms.

  1.06 ms.

 

Таким образом понятно что Table Storage работает явно быстрее чем SQL Azure. Но Sql Server 2008 R2 Express - быстрее всех.

Описание Windows Azure Storage и Azure SQL

В Windows Azure есть 3 места для хранения данных данных:


Storage
    Blob – хранилище больших элементов данных.
    Table – структурированное хранилище состояний сервиса, табличные данные без связей.
    Queue – короткие сообщения которые обеспечивает диспетчеризацию асинхронных заданий для реализации обмена данными между сервисами.
Azure SQL
     Реляционная база данных.
Driver
     Жесткий диск в формате NTFS.
 
Рассмотрим подробнее каждый их них.
Storage – общее название для Blob, Table и Queue  - все они создаются в «общем контейнере».

Доступ к ним осуществляется по адресам:
http://appname.blob.core.windows.net/<containerName>/<blobName>  для  блобов.
http://appname.table.core.windows.net/<TableName>  для таблиц.
http://appname.queue.core.windows.net/<QueueName>  для очередей.

Предназначение:

Blob – нужен для хранения больших объёмов данных, скажем видео, фото, файлов и тому подобное. Blob есть двух типов:
    1. Block Blobs – до 200 GB
    2. Page Blobs – до 1 TB.
С blob могут быть ассоциированы метаданные, которые задаются в виде пар <имя, значение> и могут достигать размера 8КБ для blob. Метаданные blob могут быть получены и заданы отдельно от данных blob.
Каждый blob должен храниться в контейнере.
У blob есть ограничения на размер загружаемого файла в 64 мб. Если размер вашего файла превышает 64 мегабайта, тогда необходимо загружать файл частями. Частями до 64 МБ каждый.

Table – хранилище структурированных данных. Одна запись может иметь до 255 свойств  (включая обязательные системные свойства: PartitionKey, RowKey и Timestamp) размер каждого свойства не может превышать 64 КБ, а суммарный размер строки не может превышать 1 МБ. Таблица (Table) – содержит набор записей. Вы можете создать любое количество таблиц.
Обязательные поля для таблицы:
    1. Ключ секции (PartitionKey) – Раздел таблицы.
    2. Ключ строки (RowKey) – Это уникальный ID сущности в рамках секции. PartitionKey в сочетании с RowKey уникально идентифицирует сущность в таблице.
    3. Временная метка (Timestamp) – Время создания или изменения, необходима для синхронизации и прочих операций.

Типы данных: PartitionKey и RowKey должны иметь тип строки и остальные свойства может быть любой из следующих типов: Binary, Bool, DateTime, Double, GUID, Int, Int64, String.

Queue – очередь содержит сообщения размер до 8КБ каждое, общее количество сообщений в очереди не ограничено. Единственное ограничение в 100 TB на размер всей очереди.

Параметры и ограничения для всего Storage:
    Вместимость - до 100 ТБ.
    Общее количество операций - до 5000 entities/messages/blobs в секунду.
    Пропускная способность - до 3 гигабит в секунду.
    Для одной очереди (Queue) - До 500 сообщений в секунду.
    Для одного раздела таблицы (Partition Table) – Для одного раздела пропускная способность составляет 500 операций в секунду. Стоит отметить что ограничение действует именно для одно раздела (Partition) а не для всей таблицы в целом.
    Для одного Blob - пропускная способность составляет до 60 Мб / сек.

 

В случае превышения лимита вы получите от сервера ошибку "503 server busy"

Azure SQL – реляционная база данных. База данных Web Edition позволяет хранить до 5 ГБ данных, база данных Business Edition позволяет хранить до 150 ГБ.
По скорости работы SQL Azure уступает Storage.

Driver – виртуальный жесткий диск с файловой системой NTFS. 

Ссылки:
http://msdn.microsoft.com/ru-ru/library/ee872420.aspx - Blob
http://msdn.microsoft.com/ru-ru/library/ee872426.aspx - Table
http://msdn.microsoft.com/ru-ru/library/ee872424.aspx - Queue
http://blogs.msdn.com/b/windowsazurestorage/archive/2010/05/10/.... - описание Storage

Настройка эмулятора хранилища Azure local Storage

Как настроить работу локального эмулятора хранилища в Azure?
Для работы этого хранилища нужен SQL сервер, локальный или какой-то внешний, но поддерживающий Windows авторизацию (т.к. я не понял где можно ввести логин и пароль для подключения)
В общем нужно запустить Windows Azure Command Prompt и выполнить команду:


В случае когда у вас локально стоит SQL сервер:
DSInit /sqlInstance: <ИМЯ ВАШЕГО ИНСТАНСА> 
Например: DSInit /sqlInstance:SQLEXPRESS

А если сервер удаленный:
DSInit /server:<ИМЯ ВАШЕГО СЕРВЕРА> 
Например: DSInit /server:192.168.1.1


Или:
DSInit /server:<ИМЯ ВАШЕГО СЕРВЕРА> \<ИМЯ ИНСТАНСА>
Например: DSInit /server:192.168.1.1\MSSQL

А для того чтобы использовать в своем проекта локальное хранилище надо модифицировать строку подключения таким образом:
Сначала в web.config или app.config:

<connectionStrings>
<add name="Storage" connectionString="usedevelopmentstorage=true" />
</connectionStrings>

И в коде:

string storageConnectionString = ConfigurationManager.ConnectionStrings["Storage"].ConnectionString;
BlobHelper helper = new BlobHelper(storageConnectionString);

 

Как создать поток C#

void RunThread()
{
System.Threading.Thread newThread;
newThread = new System.Threading.Thread(Run);
newThread.Start();
}

void Run()
{
//какая-то работа
}

WebBrowser WPF как сохранить изображение (CAPTCHA), и как изменить HTML код в странице

Столкнулся я проблемой, как сохранить динамическую картинку из браузера, например это Captcha – ведь сколько бы я не обращался по адресу картинки она каждый раз будет новая.
Для решения задачи я решил использовал WPF WebBrower, вам понадобиться подключить библиотеку Microsoft.mshtml для удобной работы с DOM.
В общем получился вот такой код, который позволяет сохранить именно ту картинку которая должна отображаться в странице, для этого: 

try
{
mshtml.HTMLDocumentClass dom = (mshtml.HTMLDocumentClass)wborwser.Document;
foreach (var item in dom.images)
{
if ((item as mshtml.HTMLImgClass).alt == "CAPTCHA")// я как-то идентифицирую нужную картинку
{
mshtml.IHTMLElement2 body2 = (mshtml.IHTMLElement2)dom.body;
mshtml.IHTMLControlRange controlRange = (mshtml.IHTMLControlRange)body2.createControlRange();
//  (item as mshtml.HTMLImgClass).
string strElName;
controlRange.add((mshtml.IHTMLControlElement)item);
controlRange.execCommand("Copy", false, System.Reflection.Missing.Value);
controlRange.remove(0);
strElName = (item as mshtml.HTMLImgClass).nameProp;
if (Clipboard.GetDataObject() != null)
{
IDataObject data = Clipboard.GetDataObject();
if (data.GetDataPresent(DataFormats.Bitmap))
{
System.Windows.Interop.InteropBitmap image = (System.Windows.Interop.InteropBitmap)data.GetData(DataFormats.Bitmap, true);
Cap_Img.Source = (ImageSource)data.GetData(DataFormats.Bitmap, true);
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(image));
string ThumbnailPath = Guid.NewGuid().ToString() + ".jpg";
FileStream stream = new FileStream(ThumbnailPath, FileMode.Create);
encoder.Save(stream);
stream.Close();
ImageSourceConverter conv = new ImageSourceConverter();
ImageSource imageSource = (ImageSource)conv.ConvertFromString(ThumbnailPath);
Cap_Img.Source = imageSource;
}
}
}
}
}
catch
{
Status.Content = "Ошибка загруки";
BusyIndicator.IsBusy = false;
}

 

В результате в папке с exe файлом появляется нужная мне картинка.

 

Дальше для заполнения полей или еще чего либо можно использовать:

dom.getElementById("TextBoxID").innerText = "какой-то текст";

 

А для имитации нажатия или клика на контрол:

 

dom.getElementById("ButtinID").click();

 

Как получить доступ из потока к элементам интерфейса в C# WPF / Silverlight

Dispatcher.BeginInvoke(new ThreadStart(delegate { 
//ваш код
}));

или

Dispatcher.BeginInvoke(new ThreadStart(()=> { 
//ваш код
}));

или

Dispatcher.BeginInvoke(()=> { 
//ваш код
});

или

Dispatcher.Invoke(new Action(() =>
{
//ваш код
}));

или

System.Windows.Application.Current.Dispatcher.Invoke(() =>
{
//ваш код
})

 

и добавить:

using System.Threading;

Кстати, никогда не используйте Dispatcher.CurrentDispatcher. 

В место него используйте Application.Current.Dispatcher.

Подробнее об этом: http://it3xl.wordpress.com