Как получить доступ из потока к элементам интерфейса в 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

Скриншот с WPF WebBrowser

Взял отсюда http://nethelp.wikidot.com/save-as-image-using-drawingimage-in-wpf

public static string GetThumbnailImage(WebBrowser CurrentBrowser)
{
Guid guid = Guid.NewGuid();
string ThumbnailPath =  guid.ToString() + ".png";
Image imgScreen = new Image();
imgScreen.Width = 120;
imgScreen.Height = 100;
imgScreen.Source = new DrawingImage(VisualTreeHelper.GetDrawing(CurrentBrowser));
FileStream stream = new FileStream(ThumbnailPath, FileMode.Create);
DrawingVisual vis = new DrawingVisual();
DrawingContext cont = vis.RenderOpen();
cont.DrawImage(imgScreen.Source, new Rect(new Size(120d, 100d)));
cont.Close();
RenderTargetBitmap rtb = new RenderTargetBitmap((int)imgScreen.Width,
(int)imgScreen.Height, 96d, 96d, PixelFormats.Default);
rtb.Render(vis);
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb));
encoder.Save(stream);
stream.Close();
return ThumbnailPath;
}

Скирншот экрана WPF

var topLeftCorner = this.PointToScreen(new System.Windows.Point(0, 0));
var topLeftGdiPoint = new System.Drawing.Point((int)topLeftCorner.X, (int)topLeftCorner.Y);
var size = new System.Drawing.Size((int)this.ActualWidth, (int)this.ActualHeight);
var screenShot = new Bitmap((int)this.ActualWidth, (int)this.ActualHeight);
using (var graphics = Graphics.FromImage(screenShot))
{
graphics.CopyFromScreen(topLeftGdiPoint, new System.Drawing.Point(),
size, CopyPixelOperation.SourceCopy);
}
screenShot.Save(@"screenshot.png", ImageFormat.Png);

Как сделать скриншот с WPF контрола

public void SaveImage(Visual visual, string filePath)
{
Rect bounds = VisualTreeHelper.GetDescendantBounds(visual);
RenderTargetBitmap bitmap = new RenderTargetBitmap((Int32)bounds.Width, (Int32)bounds.Height, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(visual);
PngBitmapEncoder image = new PngBitmapEncoder();
image.Frames.Add(BitmapFrame.Create(bitmap));
using (Stream fs = File.Create(filePath))
{
image.Save(fs);
}
}

А загрузить изображение в Image можно вот так:

ImageSourceConverter conv = new ImageSourceConverter();
ImageSource imageSource = (ImageSource)conv.ConvertFromString(name);
image.Source = imageSource;

Динамическая компиляция и в выполнение кода C#

//выполнение 
private string EvalCode(string typeName, string methodName, string sourceCode)
{
string output = ":)";
var compiler = CodeDomProvider.CreateProvider("CSharp");
var parameters = new CompilerParameters
{
CompilerOptions = "/t:library",
GenerateInMemory = true,
IncludeDebugInformation = true,
};

foreach (var reference in AppDomain.CurrentDomain.GetAssemblies())
{
try
{
parameters.ReferencedAssemblies.Add(reference.Location);
}
catch (Exception ex)
{
//Debug.WriteLine("Cannot add assembly " + reference.FullName + " as reference.");
}
}
//если надо
parameters.ReferencedAssemblies.Add(Application.StartupPath + "\\Some.dll");

var results = compiler.CompileAssemblyFromSource(parameters, sourceCode);

if (!results.Errors.HasErrors)
{
var assembly = results.CompiledAssembly;
var evaluatorType = assembly.GetType(typeName);
var evaluator = Activator.CreateInstance(evaluatorType);

output = (string)InvokeMethod(evaluatorType, methodName, evaluator, new object[] { output });
return output;
}

output = "\r\Что-то пошло не так!";
return results.Errors.Cast<CompilerError>().Aggregate(output, (current, ce) => current + string.Format("\r\nline {0}: {1}", ce.Line, ce.ErrorText));
}
//[FileIOPermission(SecurityAction.Deny, Unrestricted = true)]
private object InvokeMethod(Type evaluatorType, string methodName, object evaluator, object[] methodParams)
{
try
{
return evaluatorType.InvokeMember(methodName, System.Reflection.BindingFlags.InvokeMethod, null, evaluator, methodParams);
}
catch
{
return null;
}
}

WCF Data Services 5.0 ошибка System.Data.Services.Providers.ResourceType

Если вы делаете ODate сервисы версии 5.0 то скорее всего столкнетесь с проблемой 'System.Data.Services.Providers.ResourceType' threw an exception.'

для того чтобы это исправить нужно добавить в  Reference проекта следующие библиотеки:

Microsoft.Data.Edm.dll
Microsoft.Data.OData.dll
System.Spatial.dll

также возможно понадобиться:

Microsoft.Data.Services.dll
Microsoft.Data.Services.Client.dll

Если вы используете OpenAccess ORM то в проекте должны быть следующие библиотеки, которые должны копироваться локально:

Обязательные:
Telerik.OpenAccess.dll
Telerik.OpenAccess.35.Extensions.dll
Telerik.OpenAccess.Runtime.dll

для OData:
Telerik.OpenAccess.DataServices.50.dll

Вообще для просмотра зависимостей лучше всего использовать Telerik JustDecompile http://www.telerik.com/products/decompiler.aspx

 

Как работать с DateTime в C#

Как мы знаем тип DateTime хранит время и дату, по этому этот класс достаточно спечифично выглядит для математических операций типа получения разницы в минутах. Или добавление или вычитания времени.
1. Добавление времени:
Тут все просто DateTime.Add (AddDays, AddHours, AddMonths и т.п.) и все что с ним связано, так можно добавлять к времени дни, часы, минуты и прочее.  Если нужно вычесть то добавляйте со знаком минус.

2. Математические операции:

Для этого нам нужен прекрасный класс TimeSpan.
Например, нам нужно узнать разницу между двумя DateTime в минутах
Для этого нужно сделать:

var time = (time1 – time2);
double rez = time.TotalMinutes();

Смысл в том что операции над DateTime возвращают TimeSpan, у которого есть свойства Total* – вот там и храниться общее время в выбранных единицах.

В свойстве Minutes в данном случае будут просто текущее количество минут (скажем для 1 час, 22 минуты – там будет храниться 22 минуты. А TotalMinutes вернет 82 минуты.

В общем все операции нужно делать через TimeSpan.

По скольку данные из в TimeSpan можно получить в виде double то их можно округлить http://acroblog.acrovations.com/post/2012/09/11/Как-получить-целую-часть-или-округлить-double.aspx

Также хорошо можно использовать класс  Calendar который позволяет работать с неделями, месяцами, днями и тп.

DateTime myDT = DateTime.Now();
// Используются установленные по умолчанию календарь InvariantCulture.      
Calendar myCal = CultureInfo.InvariantCulture.Calendar;
// пример
myDT = myCal.AddYears( myDT, 5 );
myDT = myCal.AddMonths( myDT, 5 );
myDT = myCal.AddWeeks( myDT, 5 );
myDT = myCal.AddDays( myDT, 5 );
myDT = myCal.AddHours( myDT, 5 );
myDT = myCal.AddMinutes( myDT, 5 );
myDT = myCal.AddSeconds( myDT, 5 );
myDT = myCal.AddMilliseconds( myDT, 5 )

MSDN: http://msdn.microsoft.com/en-us/library/system.globalization.calendar.addweeks.aspx

Как получить целую часть или округлить double

Для этого есть стандартные функции в пространстве Math

Нас интересует:

Math.Floor – который округляет в сторону меньшего числа.

Math.Truncate – который округляет в сторону большего числа.

В зависимости от того что именно вам нужно – то и используйте.

Но скорее вам нужен именно Math.Floor, который и вернет целое число.

 

Длина строки запроса в IIS

Недавно столкнулся с проблемой когда мой запрос полностью не доходил до сервера, оказалось что по умолчанию фильтрация запросов в IIS 7.0 допускает использование URL-адресов длиной 4096 знаков и строк запросов длиной 2048 знаков. Чтобы изменить эти значения по умолчанию, добавьте в файл App.config следующий XML-код.

<system.webServer> 
<security> 
<requestFiltering> 
<requestLimits maxUrl="8192" maxQueryString="8192" /> 
</requestFiltering> 
</security> 
</system.webServer>


Это полезно когда работаешь с большими данными через, скажем XML (oData Service) или JSON, а сервер режет ваши запросы.

 

Подробнее тут http://msdn.microsoft.com/ru-ru/library/bb675150.aspx

asp.net webforms как прописать пути (Routes)

void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}

 

public static void RegisterRoutes(RouteCollection routes)
{
routes.Clear();       
//игнорирование
routes.Ignore("{resource}.axd/{*pathInfo}");
// путь по умолчанию
routes.MapPageRoute("", "", "~/Default.aspx", true, new RouteValueDictionary { });
#region Регистрация-Валидация        
routes.MapPageRoute("Login", "Login/{*parameter}", "~/Default.aspx", false);
routes.MapPageRoute("Register", "Register/{*parameter}", "~/Default.aspx", false);
routes.MapPageRoute("ChangePassowrd", "ChangePassowrd/{*parameter}", "~/Default.aspx", false);
routes.MapPageRoute("ChangePassowrdSuccess", "ChangePassowrdSuccess/{*parameter}", "~/Default.aspx", false);
routes.MapPageRoute("Profile", "Profile/{*parameter}", "~/Default.aspx", false);
routes.MapPageRoute("ValidateCode", "Valide/{*parameter}", "~/Account/ValidateCode.aspx", false);
#endregion            
#region Администратор
routes.MapPageRoute("Admin", "Admin", "~/Administrator/AdminHome.aspx", false);         
#endregion
routes.MapPageRoute("All", "{*parameter}", "~/Default.aspx", false);
//routes.MapPageRoute("All", "News/{*parameter}", "~/Default.aspx", false);
}

Как завставить WebApi возращать JSON

Все очень просто, надо в web.config в функцию Application_Start() дописать следующее:

GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();

После этого все ответы от WebAPI будут в формате JSON.

Автогенерация файла sitemap.xml в asp.net


Столкнулся я с проблемой авто генерации sitemap.xml
В общем вот что нужно делать:

1. Делаем соответствующий роут для нашего файла:

//Robots.txt
routes.MapRoute(            
name: "Robots",                
url: "robots.txt",                
defaults: new { controller = "Infrastructure", action = "Robots" });
//SiteMap.xml            
routes.MapRoute(                
name: "SiteMap",          
url: "SiteMap.xml",                
defaults: new { controller = "Infrastructure", action = "SiteMap" });

2. Сначала Robots.txt

public ActionResult Robots()
{
//мы не кешируемся
Response.AppendHeader("Last-Modified", "-1");
Response.AppendHeader("Expires", "-1");
Response.AppendHeader("Cache-Control", "no-store, no-cache, must-revalidate");
Response.AppendHeader("Cache-Control", "post-check=0, pre-check=0");
Response.AddHeader("Pragma", "no-cache");
string sitename = @"http://site.com";
string robots =
@"
User-agent: Googlebot
Allow: /
Disallow: /Scripts/
Host: site.com

User-agent: Yandex
Allow: /
Disallow: /Scripts/
Host: site.com

User-agent: *
Allow: /
Disallow: /Scripts/
Host: site.com

Sitemap: http://site.com/sitemap.xml";
Response.Write(robots);
Response.ContentType = "text/text";
return null;
}

 

3. теперь собственно сам sitemap.xml

 

public ActionResult SiteMap()
{
//мы не кешируемся
Response.AppendHeader("Last-Modified", "-1");
Response.AppendHeader("Expires", "-1");
Response.AppendHeader("Cache-Control", "no-store, no-cache, must-revalidate");
Response.AppendHeader("Cache-Control", "post-check=0, pre-check=0");
Response.AddHeader("Pragma", "no-cache");
string sitename = @"http://site.com";
//генерируем SiteMap
using (TextWriter textWriter = new StreamWriter(Response.OutputStream, System.Text.Encoding.UTF8))
{
XmlTextWriter writer = new XmlTextWriter(textWriter);
writer.Formatting = Formatting.Indented;
writer.WriteStartDocument();
writer.WriteStartElement("urlset");
writer.WriteAttributeString("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9");
//Главная
writer.WriteStartElement("url");
writer.WriteElementString("loc", sitename);
writer.WriteElementString("lastmod", DateTime.Now.ToString("yyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture));
writer.WriteElementString("changefreq", "always");
writer.WriteElementString("priority", "1");
writer.WriteEndElement();
//Главная - О нас
writer.WriteStartElement("url");
writer.WriteElementString("loc", sitename + "/About");
writer.WriteElementString("lastmod", DateTime.Now.ToString("yyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture));
writer.WriteElementString("changefreq", "always");
writer.WriteElementString("priority", "0.5");
writer.WriteEndElement();
writer.WriteEndElement();
}
Response.ContentType = "text/xml";
return null;
}

Ну вот и все :)

Авторизация Facebook, Google, OpenID в своем ASP.NET MVC проекте с помощю DotNetOpenAuth, OpenID, OAuth,

В один прекрасный момент вам понадобиться подключить авторизацию с социальных сетей, и сейчас я расскажу как это сделать.

Для начала нам надо подключить в свой проект через NuGet  сборку DotNetOpenAuth.AspNet с ее зависимостями.

В общем нам понадобиться:
DotNetOpenAuth.AspNet
DotNetOpenAuth.Core
DotNetOpenAuth.OAuth
DotNetOpenAuth.OAuth.Consumer
DotNetOpenAuth.OpenId
DotNetOpenAuth.OpenId.RelyingParty
Microsoft.Web.WebPages.OAuth
System.Transactions

Лучше использовать стандартный проект MVC 4 для основы.

Как подключить KendoUI в MVC проект

Структура архива с KendoUI:

\js - Kendo UI мнифицированые JavaScript файлы.
\styles - минифицированные стили и фоновые изображения
\src - исходники
\wrappers\aspnetmvc\Binaries -  сборки для asp.net mvc
\wrappers\aspnetmvc\Examples - примеры приложений
\wrappers\aspnetmvc\EditorTemplates - готовые шаблоны
\wrappers\aspnermvc\LegacyThemes - темы пользовательского интерфейса

Для того чтобы в вашем MVC проекте можно было использовать KendoUI MVC нужно выполнить несколько простых шагов.

1. Добавить в проект ссылку на библиотеку Kendo.Mvc.dll
Обычно находиться где-то тут:

C:\Program Files (x86)\Telerik\Kendo UI for ASP.NET MVC Q2 2012\wrappers\aspnetmvc\Binaries. В случае если вы его установили, или в архиве (сверху структура архива)


2. Добавить js скрипты
    a. kendo.web.min.js
    b. kendo.aspnetmvc.min.js (в последнее время, мне кажется что это не обязательно)


3. Добавить стили
    a. kendo.common.min.css
    b. kendo.default.min.css


4. Обязательно добавить jQuerry. Причем раньше чем KendoUI

для Razor:

 

<link rel="stylesheet" href="@Url.Content("~/Content/kendo.common.min.css")" />
<link rel="stylesheet" href="@Url.Content("~/Content/kendo.default.min.css")" />
<script src="@Url.Content("~/Scripts/jquery.min.js")"></script>
<script src="@Url.Content("~/Scripts/kendo.web.min.js")"></script>
<script src="@Url.Content("~/Scripts/kendo.aspnetmvc.min.js")"></script> (в последнее время, мне кажется что это не обязательно)

5. Добавить ссылку на библиотеку KendoUI.Mvc.dll в Web.config в раздел namespace

<add namespace="Kendo.Mvc.UI" />

Например:

<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Linq" />
<add namespace="System.Collections.Generic" />
<add namespace="Kendo.Mvc.UI" /> 
</namespaces>

 Теперь надо добавить еще одну записать в Web.config который в папке Shared

<system.web.webPages.razor>      
<pages pageBaseType="System.Web.Mvc.WebViewPage">         
<namespaces>              
<add namespace="System.Web.Mvc" />              
<add namespace="System.Web.Mvc.Ajax" />              
<add namespace="System.Web.Mvc.Html" />              
<add namespace="System.Web.Routing" />              
<add namespace="Kendo.Mvc.UI" />          
</namespaces>      
</pages> 
</system.web.webPages.razor>

Если не сделать предыдущий пункт тогда для работы нужно добавлять в начало страницы

@Using Kendo.Mvc.UI

 

 Естественно js и css стоит минифицировать.

 

Порядок JS файлов: http://acroblog.acrovations.com/post/2013/02/05/js-и-css-для-KendoUI-Порядок-подключения.aspx

Официально и подробно можно почитать тут http://docs.kendoui.com/getting-started/using-kendo-with/aspnet-mvc/introduction

 

ну теперь можно пользоваться

@(Html.Kendo().DatePicker().Name("Birthday"))

Также можно скачать расширение для студии http://visualstudiogallery.msdn.microsoft.com/65b78c2c-951e-43a8-bae7-f9039f59fb9b