среда, декабря 03, 2008

1000 commit :)

Нашему проекту ровно тысяча (1000!!!!) ле...коммитов :) с чем себя и поздравляем :)







среда, ноября 26, 2008

На тему финансовго кризиса

Похоже, финансовый кризис коснулся даже википедию:



Wiki


ps: причем если посмотреть финансовые отчеты за 2008 года (http://wikimediafoundation.org/wiki/Finance_report -> http://upload.wikimedia.org/wikipedia/foundation/4/4c/Wikimedia_20072008_fs.pdf), можно увидеть нехилые такие затраты на зарплату, путешествия :) и прочее, причем с учетом предыдущих пожертвований все равно остаются в плюсе, а денег все равно хотят :)

вторник, ноября 25, 2008

JSON в ASP.NET

исходные коды
В
предыдущей теме
Callback in ASP.NET я рассматривал, как выполнить callback со стороны клиента на сервер, так сказать, сходить за данными. Здесь я рассказываю, как можно выполнить сериализацию объекта некоего класса со стороны сервера на клиента и использовать его в гораздо более удобной и в ООП-ориентированной форме;



В рассматриваемом примере на странице создается список объектов класса Customer, декларация класса следующая:



[Serializable]
public class CustomerInfo
{
private string firstName;
public string FirstName
{
get
{
return firstName;
}
set
{
if (firstName == value)
return;
firstName = value;
}
}


private string lastName;
public string LastName
{
get
{
return lastName;
}
set
{
if (lastName == value)
return;
lastName = value;
}
}

private string company;
public string Company
{
get
{
return company;
}
set
{
if (company == value)
return;
company = value;
}
}

[NonSerialized]
private string testNonSerialized = "NonSerialized string";

}



мы пометили класс как сериализуемый атрибутом Serializable, все поля простых типов данных данного класса могут быть сериализованы, за исключением тех полей, которые мы можем отметить атрибутом NonSerialized (забегая на будущее, иногда в имеющемся классе, который мы хотим использовать на стороне клиента, могут использоваться типы данных и поля, которые мы или просто не сможем использовать на стороне клиента или же нам просто данные поля не нужны)




Заполнение данными происходит следующим образом:

///
/// databinding & controls initialization
///

private void LoadData()
{
// db request and customers collection initialization
customers.Add(new CustomerInfo
{
FirstName = "John",
LastName = "Smith",
Company = "ITS"
});

customers.Add(new CustomerInfo
{
FirstName = "Alise",
LastName = "Young",
Company = "IT Research"
});

customers.Add(new CustomerInfo
{
FirstName = "Alex",
LastName = "Gullini",
Company = "AD Analitics"
});
}



Сама страница предоставляется следующую функциональность - строит таблицу с отображением текстовых полей для редактирования firstName, lastName, company и кнопку, при нажатии на которую мы запрашиваем следующий объект для редактирования и так далее по кругу - сохранение изменений в прилагаемом примере не реализовано, только получение и отображение;



Внешний вид страницы





Сама разметка страницы следующая:


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="JSON._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
<style type="text/css">
td { border:solid 1px #eaeaea; }
</style>

<script language="javascript" type="text/javascript">
var customerID = 0;

function onClickHandler() {

serverCall('get,' + customerID);
customerID++;
if (customerID > 2) {
customerID = 0;
}
}

function onSuccessfullHandler(responseFromServer) {
var customer = Sys.Serialization.JavaScriptSerializer.deserialize(responseFromServer);
if (customer != null) {
// binding
var txtFirstName = $get('txtFirstName');
var txtLastName = $get('txtLastName');
var txtCompany = $get('txtCompany');

txtFirstName.value = customer.firstName;
txtLastName.value = customer.lastName;
txtCompany.value = customer.company;
}
else
customerID = 0;
}

</script>
</head>
<body>
<form id="frmMain" runat="server">
<asp:ScriptManager ID="scriptManager" runat="server"></asp:ScriptManager>
<div>
<table style="border:solid 1px grey;">
<tr>
<td>
First name:
</td>
<td>
<input type="text" id="txtFirstName" />
</td>
</tr>

<tr>
<td>
Last name:
</td>
<td>
<input type="text" id="txtLastName" />
</td>
</tr>

<tr>
<td>
Company:
</td>
<td>
<input type="text" id="txtCompany" />
</td>
</tr>

<tr>
<td colspan="2">
<input type="button" id="btnGetNextCustomer" onclick="onClickHandler();" value="Next customer"/>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>





Как видим, на странице используются обычные html-контролы, при нажатии на кнопку btnGetNextCustomer вызывается функция onClickHandler, которая и выполняет всю работу;


onClickHandler делает вызов функции serverCall, которую мы зарегестрировали в обработчике страницы Page_Load так как было рассказано в предыдущем моем топике, в частности, в той ее части, которая касается реализации интерфейса ICallbackEventHandler;



Страница работает следующим образом - на стороне клиента объявлена переменная customerID - это простой порядковый номер, которые передается в функцию обратного вызова serverCall, и затем этот номер увеличивается для запроса следующей записи и так далее по кругу - при достижении максимальной величины (3) он сбрасывается обратно в ноль;

При получении значения на стороне сервера в методе RaiseCallbackEvent(string eventArgument) мы сохраняем запрошенный номер во внутреннем поле currentCustomerID:




public void RaiseCallbackEvent(string eventArgument)
{
string[] argsFromClient = eventArgument.Split(',');

if (argsFromClient.Length >= 2)
{
switch (argsFromClient[0])
{
case "get":
int customerID;
if (int.TryParse(argsFromClient[1], out customerID))
{
this.currentCustomerID = customerID;
}

break;
default:
break;
}
}
}


Затем, при формировании ответа клиенту, мы сериализуем запрошенный объект Customer следующим образом:



public string GetCallbackResult()
{
string result = "{}";

if (this.currentCustomerID < this.Customers.Count)
{
CustomerInfo customer = this.Customers[this.currentCustomerID];
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(CustomerInfo));

using (MemoryStream ms = new MemoryStream())
{
ser.WriteObject(ms, customer);
result = Encoding.Default.GetString(ms.ToArray());
}
}

return result;
}


Используем класс DataContractJsonSerializer, который объявлен в пространстве имен System.Runtime.Serialization.Json и находится в сборке System.ServiceModel.Web.dll - ее нужно подключить к проекту;


Результат сериализации в строку result вы можете увидеть на следующем скриншоте - по сути дела, данная строка представляет обычное отображение javascript-объекта в строку, если мы вызываетм метод toString() - сериализация объекта в javascript достаточно простая, сохраняются просто пары ключ-значение, что логично, так как любой класс в javascript - это просто словарь.

Ответ со стороны сервера






Далее, сериализованная строка уходит на клиента, где обрабатывается в нашем сallback обработчике onSuccessfullHandler следующим образом:

function onSuccessfullHandler(responseFromServer) {
var customer = Sys.Serialization.JavaScriptSerializer.deserialize(responseFromServer);
if (customer != null) {
// binding
var txtFirstName = $get('txtFirstName');
var txtLastName = $get('txtLastName');
var txtCompany = $get('txtCompany');

txtFirstName.value = customer.firstName;
txtLastName.value = customer.lastName;
txtCompany.value = customer.company;
}
else
customerID = 0;
}





Ответ со стороны сервера




В данном случае мы используем клиентский класс Sys.Serialization.JavaScriptSerializer и его метод deserialize из библиотеки ajax - обратите внимание, для того, чтобы классы из пространства имен Sys и прочих были доступны, на странице должен быть доступен ScriptManager. Также обратите внимание, что структура самого десериализованного объекта customer полностью совпадает с его серверным описанием, таким образом, мы можем использовать объявления ранее private полей из серверного объявления класса за исключением тех, которые были помечены атрибутом NonSerialized;



Десериализованный объект customer на клиенте






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


ps: на самом деле, сам не так давно открыл для себя и начал использовать сериализацию серверных классов на сторону клиента, пока проме плюсов ничего не получил

понедельник, ноября 24, 2008

Как выполнить callback со стороны клиента на сервер в ASP.NET

исходные коды
Н
е рассматривая update panel и не используя закрытые методы класса PageRequestManager из библиотеки ajax, я выделяю для себя способы:

  1. Page methods


    Тут все достаточно просто; достаточно реализовать в web-форме статический серверный метод страницы, пометить его атрибутом WebMethodAttribute, разместить в разметке ScriptManager control, установить у него свойство EnablePageMethods и требуемый метод будет доступен через сгенерированный на стороне клиента объект PageMethods;



    В прилагаемом примере в странице PageMethods.aspx я реализовал следующий метод:




    [WebMethod(true)]
    public static string PageMethodTest(string arg)
    {
    return "this is a string from server";
    }


    На стороне клиента разместил ScriptManager следующим образом:


    <asp:scriptmanager runat="server" id="scriptManager" enablepagemethods="true">

    </asp:scriptmanager>

    И зарегестрировал серверную кнопку:



    <asp:button id="btnPageMethodInvocation"
    runat="server"
    text="Page method invocation"
    onclientclick="btnPageMethodInvocation_clientHandler();return false;">

    </asp:button>

    При клике по кнопке будет выполнен клиентский сценарий btnPageMethodInvocation_clientHandler, после чего будет возврат значения false, что говорит о необходимости разовать цепочку вызовов клиентских сценариев, одним из которыхъ является возврат формы (собственно сам postback), а именно его мы и хотим избежать; Таким образом, при клике на форму у нас должен выполниться только сценарий btnPageMethodInvocation_clientHandler;


    Сам сценарий будет следующим:

    function btnPageMethodInvocation_clientHandler() {
    PageMethods.PageMethodTest("test", onSuccessfullHandler);
    }










    Как видите, происходит обращение к глобальному клиенскому объекту PageMethods, и вызывается метод, который мы описали на серверной стороне; Сигнатура данного клиентского метода будет отличаться только наличием дополнительных параметров, которые указывают на javascript функции успешного и неуспешного вызова серверного метода, для того чтобы собственно говоря и реализовать сам принцип асинхронности – сделав вызов PageMethods.PageMethodTest, выполнение сценария не прерывается, а результат будет передан в onSuccessfullHandler функцию с единственным параметром result в случае успешного выполнение callback, как показано ниже:


    function onSuccessfullHandler(result) {
    alert(result);
    }


    Сигнатура самого метода следующая:

    Сигнатура метода


    Здесь я просто показываю значение параметра result, значение которого мы получаем со стороны сервера;


    Иными словами, все выполнение происходит следующим образом:
    ScriptManager, проанализировав codebehind класс страницы и обнаружив статик метод с атрибутом WebMethod, сгенерировал объект PageMethods и соотвествующий по сигнатуре клиенский метод, которые, собственно и реализует асинхронный вызов одноименного серверного метода, передав значение со стороны клиента; Серверный метод делает возврат значения (в нашем примере мы возвращаем простой тип данных, о том как делать возврат сложных типов данных с применением json сериализации/десериализации я расскажу в следующем посте), которое в процессе выполнения callback будет передано в клиентский сценарий, который мы указали onSuccessfullHandler;

    Подводя итог, цепочка вызовов будет следующей:

    function btnPageMethodInvocation_clientHandler()
    PageMethods.PageMethodTest("test", onSuccessfullHandler)
    public static string PageMethodTest(string arg)
    function onSuccessfullHandler(result)


    Результат вызова нашей страницы будет слеюущим:


    Результат вызова



    Данный вариант реализации асинхронного вызова очень удобен на мой взгляд, если бы не огромный минус – а именно, невозможность его использования в User-контролах;

  2. Script Service


    Второй вариант лишен описанного выше минуса; Смысл заключается в следующем – реализуется web-сервис, code behind класс сервиса помечается атрибутом ScriptService, а методы, которые мы хотим использовать на стороне клиента – атрибутом ScriptMethod; В разметке самой страницы обязательно присуствие ScriptManager с указанием того ScriptService, методы которого мы хотим получить и использовать на стороне клиента;



    В нашем случае я сделал следующий web-service:



    namespace Callbacks.ScriptServices
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ScriptService()]
    public class ScriptService : System.Web.Services.WebService
    {

    [WebMethod]
    [ScriptMethod]
    public string ScriptServiceTest(string arg)
    {
    return "this is a string from script service method";
    }
    }



    Создал страницу ScriptServiceCallPage.aspx, код разметки которой выглядит следующим образом:



    <title></title>
    <script language="javascript" type="text/javascript"
    function btnPageMethodInvocation_clientHandler() {
    Callbacks.ScriptServices.ScriptService.ScriptServiceTest("test",
    onSuccessfullHandler);
    }

    function onSuccessfullHandler(result) {
    alert(result);
    }
    </script>


    <form id="form1" runat="server">
    <asp:scriptmanager runat="server" id="scriptManager" enablepagemethods="true">
    <services>
    <asp:servicereference path="~/ScriptServices/ScriptService.asmx">
    </asp:servicereference>
    </services>
    <div>
    <asp:button id="btnPageMethodInvocation"
    runat="server" text="Script service method invocation"
    onclientclick="btnPageMethodInvocation_clientHandler();
    return false;">
    </asp:button></div>
    </asp:scriptmanager>



    </form>




    Отличие от предыдущего примера с использованием сгенерированного объекта PageMethods в том, что мы указываем конкретный ScriptService в ScriptManager, который генерирует соотвествующий javascript класс с методами, сигнатура который соотвествует серверным методам + добавляет параметры для указания javascript функций в случае успешного или неудачного выполнения асинхронного вызова; Сгенерированный объект, который мы можем использовать на стороне клиента, будет иметь имя, полностью совпадающего с указанным script service, т.е. включая c# namespace и имя класса – в нашем случае это Callbacks.ScriptServices.ScriptService; В остальном принцип работы с script service ничем не отличается от PageMethods; Достоинство данного способа состоит в том, что часто используемые операции, вызов которых требуется на клиенте, сосредоточены в одном месте, и доступны как из классов форм, так и user controls;






  3. Третий способ, который лично мне больше всего нравится и на мой взгляд наиболее гибок и прозрачнее для меня, является явная реализация интерфейса IcallbackEventHandler user контролом или классом страницы; Данный способ также описан у Дино Эспозито, автора множества книг-бестселлеров по технологиям AJAX и ASP.NET;



    В нашем примере я создал страницу ICallbackEventHandlerImplementor.aspx, у code behind класса реализовал интерфейс ICallbackEventHandler как показано ниже:


    public partial class ICallbackEventHandlerImplementor : System.Web.UI.Page, ICallbackEventHandler
    {
    #region ICallbackEventHandler Members

    public string GetCallbackResult()
    {
    string resultFromServer = "this is a string from ICallbackEventHandler implementor";
    return resultFromServer;

    }

    public void RaiseCallbackEvent(string eventArgument)
    {
    string[] argsFromClient = eventArgument.Split(',');

    if (argsFromClient.Length >= 2)
    {
    switch (argsFromClient[0])
    {
    case "add":
    break;
    default:
    break;
    }
    }
    }

    #endregion
    }


    Метод RaiseCallbackEvent будет вызываться со стороны клиентаи принимаеть едиственный строковый параметр, значение которого мы сформируем на стороне клиента; Метод GetCallbackResult будет использоваться для формирования результата, который мы вернем обратно клиентской стороне;

    Итак, что же будет являться началом асинхронной операции – а началом асинхронной операции со стороны клиента будет являться вызов функции WebForm_DoCallback, сигнатура да и собственно название которого не стоит запоминать и использовать напрямую, так они могуто измениться в следующих версиях; Вместо этого сам код для вызова мы можем получить, используя класс ClientScriptManager через свойство ClientScript текущей страницы, используй метод GetCallbackEventReference; Данный метод генерирует вызов метода WebForm_DoCallback на стороне клиента, который мы можем использовать в нашем клиентском сценарии; В нашем примере я хочу сгенерировать клиенский сценарий serverCall, который бы принимал единственное строковое значение, отправлял бы его на выполнение серверу и собственно на этом бы его функции бы заканчивались:



    Т.е. что-то типа такого:


    function serverCall(arg)
    {
    WebForm_DoCallback(…arg)
    }


    Как это сделать, показано в реализации обработчика Page_Load нашей рассматриваемой страницы:

    protected void Page_Load(object sender, EventArgs e)
    {
    if (!IsPostBack)
    {
    string webFormDoCallbackScript = this.ClientScript.GetCallbackEventReference(this, "arg", "onSuccessfullHandler", null, true);
    string serverCallScript = "function serverCall(arg){" + webFormDoCallbackScript + ";\n}\n";

    if (!this.ClientScript.IsClientScriptBlockRegistered("serverCallScript"))
    {
    this.ClientScript.RegisterClientScriptBlock(this.GetType(), "serverCallScript", serverCallScript, true);
    }

    }
    }






    Что здесь происходит? Сначала я получаю в виде строки сам вызов WebForm_DoCallback, причем указываю, как будет называться его единственный аргумент, а также имя той javascript функции, в которую будет передан результат со стороны сервера по завершении асинхронного вызова; затем я формирую функцию враппер наз функцией асинхронного вызова – а именно нашу функцию serverCall – после запуска страницы в сгенерированном исходном тексте вы увидите следующий скрипт:




    <script type="text/javascript">
    //<![CDATA[
    function serverCall(arg){WebForm_DoCallback('__Page',arg,onSuccessfullHandler,null,null,true);
    }
    //]]>
    </script>



    Теперь же можно использовать нашу функцию-враппер serverCall со стороны клиента, как показано в разметке страницы:




    <head id="Head1" runat="server">
    <title></title>
    <script language="javascript" type="text/javascript">
    function btnPageMethodInvocation_clientHandler() {
    serverCall('add,' + 10);
    }

    function onSuccessfullHandler(result) {
    alert(result);
    }
    </script>
    </head>
    <body>

    <form id="form1" runat="server">
    <div>
    <asp:Button ID="btnPageMethodInvocation"
    runat="server"
    Text="ICallbackEventHandlerImplementor sample"
    OnClientClick="btnPageMethodInvocation_clientHandler();return false;" />
    </div>
    </form>
    </body>
    </html>


    Сама разметка, как видите, практически не отличается от предыдущих страниц, за исключением того, что здесь не требуется ScriptManager; Ограничение в количестве параметров, передаваемых в функцию асинхронного вызова WebForm_DoCallback, не ограничивает однако нас от формирования такой строки, значение которой мы можем рассматривать как несколько параметров, что собственно и продемонстрировано в примере:


    На клиенте мы передаем serverCall('add,' + 10); строку “Add, 10”, на стороне сервера делаем сплит строки и дальше уже анализируем полученные значения для выполнения какого либо действия на стороне сервера незаметно от клиента;

    Лично мне последний способ нравится больше в виду того, что я получаю больший контроль над самим асинхронным вызовом, чем в первых двух описанных;



    ps: Существуют и другие способы асинхронных вызовов, например,в том же самом DevExpress есть даже специальный серверный контрол, в котором указывается javascript handler на получение результата со стороны сервера и серверный обработчик, который и выполняет анализ данных со стороны клиента;









пятница, ноября 21, 2008

No keyboard detected! Press F1 to Resume

говорят что боян

понедельник, ноября 17, 2008

Маленький Дюшес

Давно не решался на такой шаг, но все же решился (не по своей воле :))) ) , с чем себя и поздравляю...


Итак, в нашем доме поселился страшный зверь:


Дуэша

ps: зовут Duane, можно просто Дуэша, или Душка, или Дюша :-D... Тигру 2 месяца, всеяден, уже умеет ходить на горшок, постоянно требует внимания, пережил первое посещение ванных процедур, громко урчит от удовольствия, не пьет молоко :-O, хозяев пока не презирает (это временно)....

среда, октября 22, 2008

Замечательный день

Для меня этот день замечателен тем в первую очередь, что сегодня аж целых 5 !!!! лет моей дочке, во вторых тем, что у моего коллеги по работе, тоже Андрея :), родилась дочь, и по ходу ей тоже дали имя Аня :)

понедельник, августа 11, 2008

На тему icq-спама

<my uin> (13:58:38 11/08/2008)
9 августа, в субботу, рано утром в 3:35, светло-голубая жигули "классика" двигалась от ул.Подлипаева по левой полосе к автодорожному мосту. Не показывая сигнала поворота на перекрестке на ул.Пастуховскую (где заезжают к гостинице "волга"), жигули резко вывернула налево, буквально в лоб движущейся во встречном направлении нивы тёмно-фиолетового цвета. Произошел касательный небольшой по площади, но достаточно сильный удар. Водитель классики скрылся в направлении ул.Пастуховской. 100% водитель был в состоянии сильнейшего алкогольного опьянения.
>>
>> прошу всех не оставлять подобные ситуации без внимания. Ваши дети и близкие люди в любой момент могут оказаться на том свете - мы в это не верим и не понимаем, пока не наступит роковой миг.
>>
>> помогите разыскать преступника, я гарантирую вознаграждение в 3000 рублей только за достоверную информацию о местонахождении а/м жигули с поврежденным правым (со стороны пассажиров) задним крылом, и, возможно, задней дверью. Машина светло-синего, светло-голубого цвета. На машине должны остаться следы тёмно-фиолетовой краски от "нивы". Госномер преступника (возможно, неточен; 985 или 895 или 859 - варианты с буквой "

разошли дальше


Лешка (14:00:11 11/08/2008)

нет, вдруг меня найдут



<my uin> (14:00:52 11/08/2008)

молодца
отжег

ps: очень редко становлюсь участником icq spam queue, но в этот раз решил все таки поучас твовать

понедельник, июля 21, 2008

WCF-service installation on IIS|ASP.NET

Столкнулся с такой проблемой: после перестановки iis и перерегистрации asp.net перестала работать wcf инфраструктура, точнее, на все запросы операций wcf-сервиса, который хостился под iis, всегда получал 404.3;

Решение в перерегистрации самого wcf (правда, я все равно до конца так и не понял, почему wcf, изначально установленный в процессе инсталляции .net 3.5, упал после перестановки iis, возможно все вдело в кривизне моих рук)..

Проблема и решение было найдено на:
http://blogs.msdn.com/davidwaddleton/archive/2007/11/02/wcf-and-404-3-errors.aspx



kept getting 404.3 errors, so I started examining IIS to make sure that the right
stuff is registered. After not finding anything wrong, I started looking at the WCF
installation. I found that my WCF services where not installed. You can do the
installation manually by running "ServiceModelReg.exe", which was found at
%Windows%\Microsoft.Net\Framework\v3.0\Windows Communication Foundation\.




Сам процесс перерегистрации:

Проверить статус wcf:
serviceModelReg -vi


Если получим сообщение "Default Installation" - wcf установлен, иначе, требуется перестановка wcf;

Инсталляция WCF:
serviceModelReg -i


как результат, установленный под iis инфраструктура wcf;


пятница, июля 18, 2008

Перестала работать UpdatePanel :)

Что удивительно, она перестала работать :) то есть все тригерные контролы стали приводить не просто к перегрузке содержимого updatePanel, а к полной перегрузке страницы, т.е. чего хотелось избежать ( именно постбеков) так и не получилось...

причем в процессе отладки было видно, что серверный код обработчика вызывается, но на стороне клиента происходит исключение вида (все таки отладка на стороне клиентского js великая сила :)) -

Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled.

т.е. судя по всему, тот код который отдавался в процессе калбека со стороны сервера клиенту в onSuccessHandler не мог быть распарсен, что приводило к тому, что updatepanel не могла перерисовать свое содержимое, и наверно самое верное решение со стороны ajax client runtime было обновить всю страницу ..


на самом деле, сразу было очевидно то, что дело было в движке проекта или в сайте, в работе самого ajaxToolkit script manager сомневаться не приходилось, так как на отдельном простеньком сайте скрипт менеджер и update panel вели себя так как и положено;

порывшись полчаса в инете, наткнулся на интересное описание того как избежать таких ситуаций:

http://weblogs.asp.net/leftslipper/archive/2007/02/26/sys-webforms-pagerequestmanagerparsererrorexception-what-it-is-and-how-to-avoid-it.aspx

а именно:
вырезка

Why do I keeping getting a PageRequestManagerParserErrorException?

Well, chances are you're doing one of the things mentioned in the error message. Here are the most common reasons and why they don't work:

1.
Calls to Response.Write():
By calling Response.Write() directly you are bypassing the normal rendering mechanism of ASP.NET controls. The bits you write are going straight out to the client without further processing (well, mostly...). This means that UpdatePanel can't encode the data in its special format.
2.
Response filters:
Similar to Response.Write(), response filters can change the rendering in such a way that the UpdatePanel won't know.
3.
HttpModules:
Again, the same deal as Response.Write() and response filters.
4.
Server trace is enabled:
If I were going to implement trace again, I'd do it differently. Trace is effectively written out using Response.Write(), and as such messes up the special format that we use for UpdatePanel.
5.
Calls to Server.Transfer():
Unfortunately, there's no way to detect that Server.Transfer() was called. This means that UpdatePanel can't do anything intelligent when someone calls Server.Transfer(). The response sent back to the client is the HTML markup from the page to which you transferred. Since its HTML and not the special format, it can't be parsed, and you get the error.

How do I avoid getting a PageRequestManagerParserErrorException?

To start with, don't do anything from the preceding list! Here's a matching list of how to avoid a given error (when possible):

1.
Calls to Response.Write():
Place an or similar control on your page and set its Text property. The added benefit is that your pages will be valid HTML. When using Response.Write() you typically end up with pages that contain invalid markup.
2.
Response filters:
The fix might just be to not use the filter. They're not used very often anyway. If possible, filter things at the control level and not at the response level.
3.
HttpModules:
Same as response filters.
4.
Server trace is enabled:
Use some other form of tracing, such as writing to a log file, the Windows event log, or a custom mechanism.
5.
Calls to Server.Transfer():
I'm not really sure why people use Server.Transfer() at all. Perhaps it's a legacy thing from Classic ASP. I'd suggest using Response.Redirect() with query string parameters or cross-page posting.



в сущности все сводится к тому, чтобы избежать ручного responce.write(); вспомнив, что в проекте используется дополнительный httpModule, который выводит отладочную информацию и который собственно говоря и осуществляет write(), пришлось его отключить в пользу нормальной работы script manager & update panel, что и позволило избежать вышеописанной ошибки...


SQL Web Assistant procedures exceptions

SQL Server blocked access to procedure 'sys.xp_makewebtask'

Досталась в наследство следующая логика: в базе данных на определенной таблице (назовем ее не задумываясь test_table) в триггере на добавление записи пере/создавался файл в определенном каталоге, за которым собственно следил механизм типа file watcher в рамках web site - ну вот такая логика ни что не поделаешь - т.е. суть как я понимаю (до сих пор я много чего не могу понять в определенных моментах проекта) при добавлении записи в таблицу test_table дернуть сайт на выполнение определенной операции, т.е. эдакий механизм messaging & notification между sql server и web application, причем однонаправленный :)...

создание файла со стороны sql server происходило не иначе как через

master.dbo.sp_makewebtask

ну вот такой способ, суть не в этом, а в том , что при очередном переезде на новые сервера данный механизм стал глючить, а именно, при добавлении записи в таблицу test_table стал происходить exception следующего вида:


SQL Server blocked access to procedure 'sys.xp_makewebtask' of component 'Web Assistant Procedures'
because this component is turned off as part of the security configuration for this server.
A system administrator can enable the use of 'Web Assistant Procedures' by using sp_configure.
For more information about enabling 'Web Assistant Procedures',
see "Surface Area Configuration" in SQL Server Books Online.
The statement has been terminated.




Решение состоит в том, чтобы просто разрешить выполнения процедур Web Assistant Procedures:


sp_configure 'Web Assistant Procedures'
sp_configure 'Web Assistant Procedures', 1
reconfigure with override



однако, дальше случается следующее: при попытке записи в текстовый файл:


execute master.dbo.sp_makewebtask @outputfile = 'D:\Cache\cache.txt', @query = N'SELECT top 1 * FROM dbname.dbo.test_table'



получаю сообщение о невозможности произвести такую операцию, так как не хватает прав;

Решением ситуации становится разрешение для данного конкретного файла cache.txt на запись для пользователя everyone;


но и это не все :), ситуация развивается дальше:


SQL Web Assistant: Could not open the output file.


на продакшн системе ситуация следующая: sql server instance находится на одном сервере, web server application на другом,
при этом нужно настроить db server таким образом что при добавлении/изменении/удалении записей в нашу test_table срабатывал триггер,
который дергает процедуру master.dbo.sp_makewebtask, которая в свою очередь просто создает файл cache.txt в указанном каталоге (воооот)...
Но!!! сам файл должен находится на сервере web application в указанном через конфиг каталоге (помним, за ним смотрим file watcher)...
Каталог был расшарен, разрешен доступ для everyOne | quests, даны полные права на доступ, master.dbo.sp_makewebtask вызывал
с указанием пути к файлу через UNC имя, но сообщение

SQL Web Assistant: Could not open the output file.

о невозможности записи в файл так и возникало....
(Установка прав на запись для пользователя evereone ни к чему не привела, сообщение об ошибке так и возникало)

порывшись в инете, нашел решение:


How to use UNC name with sp_makewebtask in sql server

(
вырезка:


10 Apr 2008, 1:58 PM UTC
Jonathan Kehayias
These stars recognize your participation in the forums. For more information about the different levels of stars, and how points are earned, please see the FAQ.
Answerer


Posts 2,350

Answer Re: How to use UNC name with sp_makewebtask in sql server
Answer Was this post helpful ? Reply Quote


The Service Logon Account for SQL Server will need to have access to
the that shared path to read or write from there.
If SQL Server is running as Local System, you should change this to a
dedicated login account to a set user, and then grant that user
access to the shared path you want:


http://support.microsoft.com/kb/283811


Also, you can't use mapped drives like you would probably expect.
The drive is mapped at login, and is not actually a persistent drive available to the services.


)



How to change the SQL Server or SQL Server Agent service account without using SQL Enterprise Manager in SQL Server 2000 or SQL Server Configuration Manager in SQL Server 2005


http://support.microsoft.com/kb/283811



Вообщем, как итог, решение состоит в том, чтобы запустить инстанс sql server от имени учетной записи, но не local system, а той, которой разрешены
права на запись в указанный расшаренный каталог, в моем случае я просто запустил Sql server от имени administrator сервера (если подумать, то это конечно дыра в безопасности, но как временное решение до переделки самого механизма вполне достаточно):

Следующий тест должен пройти успешно:


declare @file_location varchar(100)
set @file_location = '\\unc name of web application server\TemporaryFiles\cache.txt'

execute master.dbo.sp_makewebtask @outputfile = @file_location, @query = 'SELECT top 1 * FROM dbo.test_table'





Самое интересное то, что сделав через network mapping отдельный диск, замапленный на расшаренную папку, и указав для master.dbo.sp_makewebtask путь через
такой замапленный диск, получаем предыдущее сообщение об ошибке.



Msg 16821, Level 11, State 1, Procedure sp_makewebtask, Line 131
SQL Web Assistant: Could not open the output file.




т.е. в любом случае нужно использовать unc name;

ps: sorry за сумбурную форму написания, надеюсь, данный пост будет комунить интересен и поможет в решении похожей проблемы


An error occurred creating the configuration section handler for system.serviceModel/behaviors

При очередной выкладке wcf-сервиса в рамках нашего проекта стало возникать исключение следующего плана:



Configuration Error
Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.

Parser Error Message: An error occurred creating the configuration section handler for system.serviceModel/behaviors: Extension element 'authorizationBehavior' cannot be added to this element. Verify that the extension is registered in the extension collection at system.serviceModel/extensions/behaviorExtensions.
Parameter name: element

Source Error:


Line 449:













Проблема в том, что наш Extension element -> 'authorizationBehavior' является объектом указанного через атрибут Type типа, а именно:








решением проблемы является указания full qualified name для сборки, т.е. требуется указывать номер версии, токен и культуру:









это конечно не есть хорошо (теперь при каждлой новой выкладке нужно уточнять номер версии), но другого вариант пока нет, причем такой баг был выялен только при переходе на новую development system, что удивительно потому что на старой системе такого не наблюдалось...

проблема описана здесь:
http://nayyeri.net/blog/configuration-error-for-custom-behavior-extensions-in-wcf/
https://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=216431

четверг, июля 17, 2008

DevExpress AspxExperience

Столько всего можно расписать по данной замечательной :) библиотеке, особенно о том, как красиво там реализована поддержка ajax, валидаторы, клиентские handlers, калбеки, да много всего , не перечислишь , но... пока ...точнее все еще .... в проект его не купили, или купили но ключик еще не дали :)

вообщем....дайтееее!!!! мне ключ !!!!!

крик души мля...жду полгода ....сил нет... :) ///

This message cannot support the operation because it has been copied

Собственно, возникла такая нехорошая проблема при разработке собственного message inspector, при очередной попытке прочитать body у message пришлось натолкнуться...

Проблема и ее решение описаны на официальном сайте команды разработки wcf:


http://wcf.netfx3.com/blogs/wcf_team_bloggers/archive/2006/07/26/This-message-cannot-support-the-operation-because-it-has-been-copied.aspx
http://blogs.msdn.com/drnick/archive/2006/07/26/This-message-cannot-support-the-operation-because-it-has-been-copied.aspx



можно привести кусок кода в моем случае:

protected override Message OnAfterReceivedRequest(string authToken, Message request)
{

// проблема описана в WCF
// http://wcf.netfx3.com/blogs/wcf_team_bloggers/archive/2006/07/26/This-message-cannot-support-the-operation-because-it-has-been-copied.aspx
// http://blogs.msdn.com/drnick/archive/2006/07/26/This-message-cannot-support-the-operation-because-it-has-been-copied.aspx
// This message cannot support the operation because it has been copied
// This message cannot support the operation because it has been readed

MessageBuffer buffer = request.CreateBufferedCopy(int.MaxValue);
Message returnMessage = buffer.CreateMessage();
string parameters = buffer.CreateMessage().GetReaderAtBodyContents().ReadInnerXml();
buffer.Close();


string action = request.Headers.Action;
AuthorizationManager.RegistryOperationInvocation(authToken, action, parameters);

return returnMessage;
}



т.е. суть решения сводится к тому, чтобы работать каждый раз с копией message, а не с самим сообщением...

Ajax: The system cannot locate the resource specified;

При отладке ajax вдруг стала происходить странная ошибка в коде вызова ScriptMethod-а отдельно выделенного ScriptService,
в частности я дебажил некоторый модуль .ascx, в котором происходит обращение к объекту-прокси, созданному на стороне клиента:
код на стороне клиента js:

Sys.Debug.fail('');
if (typeof(siStatuses) != "undefined" && siStatuses != null)
{
WS.Scripts.ScriptService.CheckStockImagesDownloading(siStatuses, OnCheckComplete, OnCheckFailed);
}


при обращении происходил exception на стороне клиента вида:
The system cannot locate the resource specified;

который возникал уже при самом последнем обращении к ядру передачи собственно сообщения в теле калбека, а именно
где то в коде:

Sys.Net.WebServiceProxy.invoke(servicePath, methodName, useGet, params, onSuccess, onFailure, userContext, this.get_timeout());

........
this._xmlHttpRequest.send(body);



путем логического осмысления :) пришел к выводу что длина сообщения, передаваемого в scriptMethod была
значительно больше чем килобайт, указанный собственно говоря через атрибут UseHttpGet:


[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]


гораздо больше...:)) ну и соотвественно напрашивается вывод (чисто логически потому что более менее внятного сообщения об ошибке от ie я не смог получить, или просто не смог докопаться до самых недр) что xmlHttpRequest object просто не может совершить
такое обращение, путем перестановки на


[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = false)]




т.е. мы разрещаем передачу сообщения только методом post, что значительно расширяет возможности самой передачи и снимает ограничение на длину сообщения, что собственно и лечит данную злокачественную опухоль... вылечена; :)

понедельник, июля 07, 2008

Верх насилия над собой (или как отпилить сук, на котором сидишь)

Разочарование ждет того, кто промахнется мышкой вместо properties на disable button в окне internet status, находясь в терминальной сессии...



ps: как минимум, общение с провайдером
pps: сразу хочется вспомнить хорошими словами всех юзабилистов windows


среда, июля 02, 2008

Frontier

Приготовьтесь к настоящему кошмару!



Давно уже не трогают фильмы такого рода, но данный фильм (граница), снятый Люком Бессоном, оставил свое впечатление от моря крови, бескомпромиссной жестокости, мелочей в деталях, осознания того, что есть или даже могут быть люди с другим мировозрением, образом жизни, прямо противопоставленным общепринятому и который для них является единственно возможнным и необходимым - все это есть фильм frontier...



Но самое большое впечатление произвел сонг от AWIM - Kill Me, в заставке я тот короткий фрагмент, который присутствовал, прокручивал раз 10 наверно, сегодня прослушал полный
на http://www.youtube.com/watch?v=2Ku9_etu9UU



Сам обхор фильма и комменты к нему можно посмотреть на кинопоиске

http://www.kinopoisk.ru/level/1/film/266142/





ps: текст песни сохраню хотя бы здесь:

Kill Me
By Awim



Loving your dream,
carrying your pain.
Watching me going
slowly to my grave.
Didn't know you,
didn't know you.
Sipping hatred in a
glass of milk.
Injecting fears in my
brittle little veins.
Didn't know you,
didn't know you.

Talking nonsense to me,
I wish i could believe.
Living me untended
so little left to give.

Kill me I'm a monster
you made me cruel but I'm
not a failure.
Kill me I'm a monster
I beg you now cause I'm
not a killer.
Heal me I'm a monster
You spill my blood cause I'm
just a dreamer.
Kill me I'm a monster
You made me cry it will
soon be over.
Kill me I'm a monster
You made me cruel but I'm
not a failure.
Kill me I'm a monster
You made me cry it will
soon be over.


Floating in your dream
driven by your aim.
Faking to be in
laughing at my pain.
laughing at my pain.

Needed just a ride
with a lovely maid.
Sifting trough your light
tearing me to shreds.
Blood's coming to my head.

Kill me I'm a monster
you made me cruel but I'm
not a failure.
Kill me I'm a monster
I beg you now cause I'm
not a killer.
Heal me I'm a monster
You spill my blood cause I'm
just a dreamer.
Kill me I'm a monster
You made me cry it will
soon be over.
Kill me I'm a monster
You made me cruel but I'm
not a failure.
Kill me I'm a monster
You made me cry it will
soon be over.

среда, мая 28, 2008

Could not load file or assembly 'AjaxControlToolkit' or one of its dependencies. The parameter is incorrect.

При компиляции появляется ошибка:


Could not load file or assembly 'AjaxControlToolkit' or one of its dependencies. The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))



решение:

удалить содержимое папки, указанный через атрибут tempDirectory секции compilation в web.config сайта, в моем случае


<compilation debug="true" defaultlanguage="cs" tempdirectory="C:\ASPTemporary files">



это был каталог
C:\ASPTemporary files\<web application dir>,

если атрибут не указан, то это будет каталог следующего вида:
<%win dir%>\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\<web application dir>



среда, мая 14, 2008

Ajax TabContainer control

Проблема описана:
http://www.kiko-santos.com/2007/02/tab-ajax-control-toolkit-style-problem/

собственно сама проблема в том, что
при попытке использовать Ajax TabContainer control стали некорректно отрисовываться заголовки табов,

решение такое: на странице разместить следующие стили:




.ajax__tab_default .ajax__tab_inner {height : 100%;}
.ajax__tab_default .ajax__tab_tab {height : 100%;}

.ajax__tab_xp .ajax__tab_hover .ajax__tab_tab {height : 100%;}
.ajax__tab_xp .ajax__tab_active .ajax__tab_tab {height : 100%;}

.ajax__tab_xp .ajax__tab_inner {height : 100%;}
.ajax__tab_xp .ajax__tab_tab {height:100%}
.ajax__tab_xp .ajax__tab_hover .ajax__tab_inner {height : 100%;}
.ajax__tab_xp .ajax__tab_active .ajax__tab_inner {height : 100%;}





Также интересная тема насчет кастомизации tab:


http://clanmonroe.com/Blog/archive/2008/05/09/applying-unique-styles-to-tabs---ajaxcontroltoolkit.aspx

суббота, апреля 05, 2008

Красный дракон

...

- Сколько ты еще пробудешь в атланте? не подумай, я не собираюсь тебя просить побыстрее возвращаться домой. просто хочу знать.

- понятия не имею, по крайней мере еще несколько дней. я так скучаю по тебе.

- я тоже. я тебя хочу.

- о боже, боюсь, я этого не выдержу. давай не будем.

- не будем что?

- говорить об этом.

- ладно, но думать то об этом можно?

- конечно.

- у нас новая собака.

- о господи!

- что-то среднее между бассетом и пекинесом.

- замечательно.

- с большущими яйцами.

- меня не интересует, какие у него яйца.

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

- он не может их втягивать.

- может. ты ничего не понимаешь.

- понимаю.

- а ты свои можешь втягивать?

- я так и знал, что мы к этому придем.

- ну так как, с яйцами-то?

- ну, если уж тебе так интересно, то один рах втягивал.

- когда же?

- в молодости. когда пришлось быстро перепрыгивать через забор из колючей проволоки.

- зачем?

- да я нес арбуз с чужого огорода.

- ты что, удирал? от кого?

- от одного знакомого свинопаса. он услышал, как залаяли собаки, и выскочил из дому в трусах и с двухстволкой. к счастью, споткнулся и дал мне фору.

- он стрелял в тебя?

- тогда я думал, что да. хотя этот звук могла произвести и моя задница. с перепугу. так что я до сих пор не знаю, кто из нас стрелял.

- ты перепрыгнул через забор?

- запросто.

- ясно. преступные наклонности с дества.

- нет у меня никаких преступных наклонностей.

...

ps: (с)Томас Харрис ~Красный Дракон~

понедельник, марта 17, 2008

The target assembly contains no service types

В прокте используется WCF, причем сами контракты определены в одной сборке (Project.Services.Library as example), а реализации сервисов в другой (Project.Services.MyService as example), а хостились сервисы под asp.net - т.е. наружу выставлял из проекта (Project.Site) только .svc файл...

Вот........:) Cобственно, стала возникать такая проблема, при старте Project.Site (asp.net application) стало возникать сообщение в модальном диалоге:


The target assembly contains no service types

причем появились жуткие тормоза, что не особенно доставляло радости к процессу отладки и так без того досточного тяжелого asp.net приложения...

Решение, по крайне мере, для моего тяжелого случая, оказалось на
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2687265&SiteID=1


если коротко, из файла проекта с*.csproj определением контракта wcf-сервиса нужно просто удалить следующую строку:
<projecttypeguids>{3D9AD99F-2412-4246-B90B-4EAA41C64699};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</projecttypeguids>>






вторник, марта 11, 2008

8 Марта

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



Историю же празднования Международного женского дня принято связывать с именем революционерки Клары Цеткин. Именно она на международной конференции женщин в 1910 году в Копенгагене провозгласила идею ежегодно отмечать 8 марта как день рождения женского пролетариата. Выбор Цеткин именно 8 го марта в качестве даты празднования Международного женского дня вызывает разноречивые объяснения. Согласно официальной, широко известной версии, Женский день был приурочен к событиям 1857 года, когда 8 марта текстильщицы нью йоркских фабрик прошли маршем по улицам города. Они требовали 10часовой рабочий день, светлые и сухие рабочие помещения, равную с мужчинами заработную плату. Работали в то время женщины по 16 часов в сутки, получая за свой труд гроши.


Мужчинам после решительных выступлений удалось добиться введения 10 часового рабочего дня. На многих предприятиях в США возникли профсоюзные организации. В то историческое 8 марта во многих городах Америки сотни женщин вышли на демонстрацию, требуя представленияим избирательного права.


Однако ряд историков называют и другую религиозную причину возникновения праздника, согласно которой в намерения Цеткин входило связать историю женского социалистического движения с историей ее народа евреев. А именно с той страницей этой истории, которая рассказывает об Эсфири, жене персидского царя Ксеркса.

Царица Эсфирь, воспользовавшись действием на Ксеркса своих чар, спасла иудеев от истребления. Взяв с царя, не знавшего о ее происхождении, обещание, что он уничтожит всех врагов, которые покушаются на ее народ, Есфирь предотвратила планировавшиеся «еврейские погромы».


Есфирь обратила царский приказ против самих персов, желавших истребить иудеев, в честь чего день 13 Адара (этот месяц еврейского календаря приходится на конец февраля начало марта) стал праздноваться как праздник Пурима. Дата празднования Пурима в иудейском религиозном календаре является «скользящей», как в православном дата празднования Пасхи. Однако число празднования Пурима, пришедшееся в 1910 году на 8 марта, закрепилось и прижилось.


В 1911 году Женский день впервые отмечался 19 марта в Австрии, Дании, Германии и Швейцарии. Тогда более миллиона мужчин и женщин приняли участие в манифестациях. Кроме права избирать и занимать руководящие посты, женщины добивались равных производственных прав с мужчинами.


В России впервые Международный женский день отмечался в 1913 году в Петербурге. В прошении на имя градоначальника было заявлено об организации «...научного утра по женскому вопросу». Власти дали разрешение, и 2 марта 1913 года в здании Калашниковской хлебной биржи на Полтавской улице собралось полторы тысяч человек. Повестка дня научных чтений включала следующие вопросы: право голоса для женщин; государственное обеспечение материнства; дороговизна жизни. В 1917 году женщины России вышли на улицы в последнее воскресенье февраля с лозунгами «Хлеба и мира». Через 4 дня император Николай II отрекся от престола, временное правительство гарантировало женщинам избирательное право. Этот исторический день выпал на 23 февраля по юлианскому календарю, который в то время использовался в России, и на 8 марта по григорианскому календарю. Международный женский день 8 марта с первых лет Советской власти стал государственным праздником. С 1965 года этот день стал не рабочим.


Существовал и праздничный ритуал: в этот день на торжественных мероприятиях государство отчитывалось перед обществом о реализации политики в отношении женщин.
Постепенно Международный женский день в стране терял свою политическую окраску.


В 1977 году Организация объединенных наций объявила 8 е марта Международным женским днем. Слово «борьба» из названия праздника исчезло, а 8е марта стало праздником женщин, весны и любви.
После распада Советского Союза день 8 марта остался в перечне государственных праздников Российской Федерации. Отмечается Международный женский день и в странах СНГ: в Азербайджане, Грузии, Казахстане, Киргизии, Молдавии, Таджикистане, Туркмении, Украине, Белоруссии.


ps: не мое, наткнулся и нагло стырил чтобы потом не искать :)

четверг, марта 06, 2008

Одноклеточный попугай

ps: сказано про нашего yahoo - Яшу-попугая, из песни слов не выкинешь, и самое главное ведь - не придерешься, клетка то одна :)

среда, марта 05, 2008

Только что у нас в стае товарищей 8го этажа родилось высказывание:
порнопрограммирование в оральном режиме:)
на манер парного программирования в авральном режиме

понедельник, марта 03, 2008

This collection already contains an address with scheme http.

При очередной выкладке одного из WCF сервисов возникла проблема с настройкой сервиса на продакшн-сервере, получаем постоянно исключение следующего вида (уточнение, сам сервис хостился в среде asp.net в web приложении на iis, доступном сразу по нескольким хостам, приложение по сути является порталом, хостящим разные сайты):



This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.
Parameter name: item


Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentException: This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.
Parameter name: item



решение:

Данная ситуация случается в том случае, когда wcf-сервис может быть достугнут сразу по нескольким адресам....т.е. в нашем случае важно было указать из всех доступных хостов по указанному ip-адресу, на котором хостился web - сервис, только один в разрезе различных доступных binding-протоколов, как показано ниже в примере:


ссылки по теме:
http://blogs.msdn.com/rampo/archive/2008/02/11/how-can-wcf-support-multiple-iis-binding-specified-per-site.aspx



How can WCF support multiple IIS Binding specified per site ?


Background

IIS has web sites, which are containers for virtual applications which contain virtual directories. The application in a site can be accessed through one or more IIS binding.

IIS bindings provide two pieces of information – binding protocol and binding information. Binding protocol defines the scheme over which communication occurs, and binding information is the information used to access the site.

Example

Binding protocol – HTTP

Binding Information – IPAddress , Port, Hostheader

IIS supports specifying multiple IIS bindings per site, which results in multiple base addresses per scheme. A WCF service hosted under a site allows binding to only one baseAddress per scheme.



Solution in .Net Fx 3.0:Supporting Multiple IIS Bindings Per Site

Solution in .Net Fx3.5: BaseAddressPrefixFilters





Specifying a prefix filter at the appdomain level via config allows for filtering out unnecessary schemes. The incoming base addresses, supplied by IIS, are filtered based on the optional prefix list filter. By default, when prefix is not specified all addresses are passed through. Specifying the prefix will result in only the matching base address for that scheme to be passed through.


Example


   <system.serviceModel>

<serviceHostingEnvironment>

<baseAddressPrefixFilters>

<add prefix=”net.tcp://payroll.myorg.com:8000”/>

<add prefix=”http://shipping.myorg.com:9000”/>

</baseAddressPrefixFilters>

</serviceHostingEnvironment>

</system.serviceModel>





In the above example, net.tcp://payroll.myorg.com:8000 and http://shipping.myorg.com:9000 are the only base addresses, for their respective schemes, which will be allowed to be passed through. The baseAddressPrefixFilter does not support any wildcards .

The baseAddresses supplied by IIS may have addresses bound to other schemes not present in baseAddressPrefixFilter list. These addresses will not be filtered out.



ссылки по теме:

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=373333&SiteID=1
http://www.robzelt.com/blog/2007/01/24/WCF+This+Collection+Already+Contains+An+Address+With+Scheme+Http.aspx
http://www.bokebb.com/dev/english/2047/posts/204720109.shtml

среда, февраля 06, 2008

IE Developer Toolbar

Вообщем, вещь незаменимая для анализа контента страницы (скачать можно здесь - IE DevToolbar), но вот так получилось, что несколько раз сам этот плагин "ломался", посему:

проблемы, которые возникают:

IE developer toolbar может глючить на windows vista, для лечения рекомендуется временно отключить protected mode или запустить IE через панель start->programms по правому клику, выбрав в контекстном меню run as administrator...

еще проблема, из-за которой многие начинают нервничать: — панель показывается, но все опции заблокированы (keywords: IE Developer toolbar All options are disabled)... Тут все просто, идем в Tools-> Manage Add-ons-> Enable or Disable Add-ons — возможно, по какой то причине IE заблокировал работа данного плагина, тогда просто делаем его снова Enable, и все возвращается к нормальному режиму работы....


Еще один интересный плагин, который не плохо сочетается в связке с IEDevToolbar — DebugBar — смотреть можно здесь — http://www.debugbar.com/