среда, мая 24, 2006

WSS Login

Многие сомневаются в существовании означенной веб-части. Вот же она - в виде кнопки "Вход":


вторник, апреля 18, 2006

Sharepoint WebParts in VS 2005

Последнее усилие получить что-то пристойное в смысле использования Visual Studio 2005 для разработки WebPart'ов для Sharepoint'а.
Вот здесь - шаблон проекта. С его помощью создаётся вполне работоспособное хозяйство для разработки и компиляции веб-частей.
Где-то также нашлись codesnippet'ы, но не очень интересные, по-правде. В общем, для редактирования 2005-я студия получше будет.
Только вот с отладкой - никак, 2005-я нужного режима вовсе не имеет. Сделал проект на 2003-й Студии, включил туда тексты (отладка не запускается без компиляции) - и можно отлаживать. Если не очень часто это делать - пригодно для жизни получилось.

воскресенье, апреля 16, 2006

Очередной прикол Sharepoint

При копировании списков для полей типа SPFieldNumber использовал конструкцию:

newfield.MaximumValue = field.MaximumValue;

newfield. MinimumValue = field.MinimumValue;

Первая строчка проходит, на второй же вылетает исключение с сообщением типа "Значение сильно большое или сильно маленькое для типа Double". Проходит только значение по умолчанию (ок. -1e308, когда значение не устанавливалось), если в исходном списке такое значение было установлено, то кранты. Через Reflection нужное значение присвоить тоже не удаётся. :-(
Хуже того, исполнение первой строчки вызывает то же исключение при попытке отредактировать это поле в интерфейсе _layouts/1049/FldEdit.aspx.

Пришлось в Админе от установки этих свойств отказаться с выдачей предупреждения.

Вот, блин.

понедельник, марта 27, 2006

MSMQ on Windows Mobile 5

Решил попользоваться означенной фигнёй.
Скачал дистрибутив, установил – не работает :-(
Порылся в Гугле, выяснилось, что это у многих так. Но поправимо – надо руками активировать сей девайс:

[DllImport("coredll.dll",CharSet=CharSet.Unicode)]
public static extern IntPtr ActivateDevice(string lpszDevKey, int dwClientInfo);
...
IntPtr id = ActivateDevice(@"Drivers\BuiltIn\MSMQD", 0);
...

После этого хозяйство подаёт признаки жизни.

Дальше сделал попытку создать очереди и сунуть в них сообщения – ну, по примерам в MSDN и проч. литературе.
private void Testmenu_Click(object sender, EventArgs e) {
Qname = @"FormatName:DIRECT=OS: DkmServ\qtek";
Qname = @".\Private$\ttrqueL";
Qname = @".\ttrqueP"; MessageQueue.GetMachineId(".");
if (!MessageQueue.Exists(Qname)) {
msgs = MessageQueue.Create(Qname);
} else {
msgs = new MessageQueue(Qname);
}
msgs.Send("Hello, Прювет");
} catch (Exception err) {
MessageBox.Show(err.Message, err.GetType().Name);
}
}

Выяснилось, что можно оперировать только с приватной очередью, все прочие вариантыпадают. Да ещё с сообщением о невозможности вывести сообщение в связи с отсутствием какой-то нужной для этого сборки.
В общем, очередная недоделка. Пущай полежит до следующей версии. Программки на одной машине как-нить и без MSMQ согласую.

четверг, марта 16, 2006

Очередной прикол Sharepoint

Обнаружил, что в одном месте - в базе данных содержимого Sharepoint (в случае портала - в базе portal1_SITE) в таблице Sites (поле FullUrl ) пишутся абсолютные значения адресов (наподобие http://server/sites/site1).
Пишутся они туда только для узлов верхнего уровня в момент их создания и, похоже, больше нигде не используются. Вместо них можно свободно написать любые матерные слова, сайты работают нормально.
Во всех остальных местах пишутся относительные адреса сайтов и узлов.

Реликт какой-то, похоже...

воскресенье, марта 05, 2006

Секреты, едрёныть :(

Возился с задачами Outlook на десктопе и на мобиле. Всё хорошо и красиво, синхронизируются, можно что-то записать, записанное хранится.Но только на первый взгляд. На второй взгляд – неясно, как синхронизируется: идентификаторы на десктопе и на мобилке друг на друга вовсе не похожи. Где-то ещё таблицы должны храниться...Кроме того, добавляемые пользовательские свойства (даже с одинаковыми именам) не пересылаются. Вот же блин!

суббота, февраля 11, 2006

Очередной прикол Sharepoint'а

Теперь прикол от Sharepoint Portal.

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

WebPart dst = new WebPart ();
SPWebPartCollection wpc = file.GetWebPartCollection(Storage
.Shared);
Guid
ID = wpc.Add(dst);
WebPart ds = wpc[ID];
//добавленный контрол
ds.ZoneID = ZoneID;
//присвоить значения другим свойствам
wpc.SaveChanges(ID);

Оказалось, на страницах портала есть зоны (одна из них - TitleBar), которым небезразличен порядок действий.

пятница, февраля 10, 2006

Sharepoint & Anthem.NET

Nice work Anthem.NET I used in the small Web-part, containing TextBox and LinkButton . For the conclusion of communications there is Label control.

The method of use came out sufficiently simple.
Connecting to namespace Anthem:
#if AJAX
using
Anthem;
#else
using System.Web.UI.WebControls;
#endif

Addition of specific properties in method OnInit:
#if AJAX
btn.TextDuringCallBack = "..Wait";
btn.EnabledDuringCallBack = false;
#endif

Everything earned after this, as it was expected:
- the button is blocked to the period of the fulfillment of actions, the inscription is derived on it"..Wait"
- on the return draw again only changed elements (button, label and text field), without the stupid pulling of the entire page.

Underwater stones thus far were located two:
1. During the changes in js-code and the recompilation of project Anthem-2003 is necessary cleaning AppPool the corresponding Web site.
2. Values UpdateAfterCallBack=true; in method OnInit to establish one ought not - immediately occurs copying with the original values. To establish them is possible either in the events handlers or in the beginning of method RenderWebPart.

Sharepoint & Anthem.NET

Отличную разработку Anthem.NET использовал в небольшой веб-части, содержащей TextBox и LinkButton (не считая выполняемых действий). Для вывода сообщений имется Label.

Метод использования получился довольно простой.

В файле вебчасти, использующей web-контролы, подключил пространство имён Anthem:
#if AJAX
using Anthem;
#else
using System.Web.UI.WebControls;
#endif

В методе OnInit для имеющейся на веб-части кнопки btn добавил cпецифические свойства:
#if AJAX
btn.TextDuringCallBack = "..Wait";
btn.EnabledDuringCallBack =
false;
#endif

Собственно, после этого всё заработало, как и ожидалось:
- на время выполнения действий кнопка блокируется, на ней выводится надпись "..Wait"
- по возврату перерисовываются только изменившиеся элементы (кнопка, метка и текстовое поле), без дурацкого дёргания всей страницы.

Подводных камней пока нашлось два.
1. При изменениях в js-коде и перекомпиляции проекта Anthem-2003 необходима очистка AppPool соответствующего веб-сайта.
2. Значения UpdateAfterCallBack=true; в методе OnInit устанавливать не следует - сразу происходит перерисовка исходными значениями. Устанавливать их можно или в обработчиках событий или в начале метода RenderWebPart.

четверг, февраля 09, 2006

«About» ToolPart continued

В развитие примочки перенёс в эту панель запуск функции, которая запускалась из меню веб-части и не давала покоя любопытным юзерам. Сделал там кнопочку, всё хорошо, всё выполняется. Ура!

Но Microsoft не дремлет! И тут нашлась засада...

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

ParentToolPane.OK.Visible =
ParentToolPane.Cancel.Visible =
ParentToolPane.Apply.Visible = false;

Минное поле...

пятница, января 27, 2006

«About» ToolPart

Подсмотрел у кого-то и поразвивал примочку для вывода панельки «About…» в панели настройки веб-части.
Сам класс панели :

public class About: Microsoft.SharePoint.WebPartPages .ToolPart
{
      public About()
      {
            this . Title = "O
веб -части..." ;
      }
      string bCard="© DkmS, 2005..06 ";
      /// <summary>
      /// Parent Webpart
      /// </summary>
      public WebPart ParentWP{
            get{return parent;}
            set {parent= value;}
      }
      protected override void OnInit(EventArgs e) {
            base .OnInit (e);
      }
      public override void ApplyChanges(){}
      public override void SyncChanges(){}
      public override void CancelChanges(){}
      protected override void RenderToolPart(HtmlTextWriter output){
            output .Write("<center>" );
            output.Write( "<div title='"+bCard +"'>");
            output.Write("<br><b>My cool WebPart.</b><br><br>" );
            output.Write("</div>");
            output . Write("</center>");
            output.Write("<br><br><hr>" );
      }
}

Использование:

В вызывающем классе изменяем метод

public override ToolPart[] GetToolParts() {
      ToolPart[] baseTP = base .GetToolParts ();
      ToolPart[] myTP =new ToolPart[3];
      WebPartToolPart std=baseTP[ 0] as WebPartToolPart;
      CustomPropertyToolPart myprops=baseTP[1] as CustomPropertyToolPart;
      myTP[0]=myprops;

      myTP[2]=std;
      About about=new About();
      about.ParentWP= this;
      myTP[1]=about;
      return myTP;
}

среда, января 25, 2006

Обработка обращения к IIS по "неправильному" порту.

Сильно похоже, что до web-сервера запросы вида http://server:port в случае, когда обработка такого порта на самом сервере не предусмотрена, просто не доходят.
Сообщение типа The page you are looking for is currently unavailable (вариант английского IE) формирует сам браузер. Например, русский Firefox в таких случаях сообщает: Попытка соединения не удалась. Firefox не может установить соединение с сервером server:port. У IE такая же реакция наблюдается и при обращении к заведомо несуществующему серверу (http://nonexistserver). FF при этом пытается организовать поиск при помощи Google.
 
Поэтому сделать некий универсальный обработчик таких обращений невозможно. Можно лишь сделать обработку ставших недействительными существовавших ранее обращений путём организации виртуального сервера, обрабатывающего запросы с использованием "неверного порта". При обработке можно как перенаправлять запросы, так и формировать какие-либо сообщения.
 

четверг, января 19, 2006

Очередной прикол от Sharepoint

При реализации "Удаления" записей списка в "корзину" добавил к списку поле _deleted_ типа Boolean, в который ставил признак "удаления".
Но не всё так просто, MS лёгких путей не ищет:
конструкция list.Items.GetDataTable(); иногда возвращает в этом поле DBNull, иногда и правильные значения.
В итоге пришлось сделать поле целого типа и проверять на == 1.
 
Блин.

Application settings in C# 2.0 continued

Обнаружилась засада - не может засады не быть!
 
Для проекта типа "Class Library" можно задать настройки ровно так же, как и для проекта "Application". Разница небольшая - при загрузке сборки чтения конфига не происходит. Даже принудительное перечитывание при помощи settings.Reload(); ничего не прибавляет. Модуль работает с теми значениями настроек, которые были записаны в качестве default'ных.
 
Пришлось написать процедуру считывания значений настроек.

void LoadSettings(ref object settings) {
    PropertyInfo[] props = settings.GetType().GetProperties();
   
string path = this.GetType().Assembly.Location;
   
string cfgpath=path+".config";
   
if (! File.Exists(cfgpath)) return;
   
XmlDocument cfg = new XmlDocument();
   
try {
        cfg.Load(cfgpath);
    }
catch (Exception err) {
        ....
       
return;
    }
   
foreach (PropertyInfo prop in props) {
       
if (!prop.CanWrite) continue;
       
XmlNode setting = cfg.SelectSingleNode("//setting[@name = '" + prop.Name + "']" );
       
object value = "";
        if (setting != null) {
            
try {
                value = setting.SelectSingleNode(
"value").InnerText;
               
prop.SetValue(settings, value, null);
           
} catch { }
        }
    }
}

Использование:

object osettings = new Settings();
LoadSettings(
ref osettings);
settings = (
Settings)osettings;

Примечание. При настройке параметров в VS 2005 область действия (Scope) следует установить User (иначе будет сгенерён класс Settings с readonly свойствами).

вторник, января 17, 2006

«Секретная» страница

Соорудил aspx-страницу с авторизацией.
Для каждого юзера выдаётся список предназначенных для него файлов, которые можно сгрузить.
Регулируется вот таким конфигом:

<?xml version="1.0" encoding="utf-8" ?>
<users>
<user dirs="adir" pwd="ap" name="anton">
<user dirs="*" pwd="dp" name="DkmS">
</users>


Вполне даже симпатично получилось. Заодно кой-чему научился.

воскресенье, января 15, 2006

Settins & Versions

Хорошая вещь Properties.Settings, но не до конца продуманная.
Засада - в хранении пользовательских настроек. Без всяких споров/разговоров сохраняются в файле %USERPROFILE%\Local Settings\Application Data\<Company Name>\<appdomainname>_<eid>_<hash>\<verison>\user.config .
И вот из-за этой <verison> и всё горе - используется значение атрибута assembly:AssemblyVersion , которое у меня обычно выставляется автоматом наподобие "1.0.0.*", что довольно удобно при протоколировании . Но при отладке всё, естественно, корёжится.
Пришлось начать использовать атрибут assembly:AssemblyFileVersionAttribute, который студия (Express, по меньшей мере) автоматом менять не умеет. Для получения версии исполняемого файла пользуюсь процедурой
public static string AnyVersion( Assembly assembly) {
object[] attrs=null;
try{
    attrs=assembly.GetCustomAttributes(
typeof(AssemblyFileVersionAttribute ),false);
}
catch{}
if (attrs != null && attrs.Length > 0) {
   
return ((AssemblyFileVersionAttribute)attrs[0]).Version;
}
return assembly.GetName().Version.ToString(4);
}
 
Использование - AnyVersion(Assembly.GetExecutingAssembly()) или ещё как...

четверг, января 12, 2006

Application settings in C# 2.0

Использование новых возможностей по конфигурированию приложений в VS 2005 применительно к VB.NET описано вот тут.

В C# настройка средствами VS (в т.ч. Express Edition) выполняется точно так же. Отличается, ввиду отсутствия в C# конструкции My.Settings, способ использования этих средств.

В модуле, где необходимо использовать настройки, нужно подключить пространство имён Properties:

using MyProgram.Properties;

В соответствующем классе объявить член класса:

private Settings settings = new Settings();

Поля этого класса уже можно использовать по назначению:

this.Size = settings.MainFormSize;

Замечание.

Такую же операцию следует выполнить во всех использующих настройки модулях (классах, формах и т.п.).


среда, декабря 28, 2005

Из Writely

Из C# Express через Word: с заменой абзаца на разрыв строки

/// <summary>
///
Description for XmlView.
/// </summary>
[DefaultProperty("Text"),
ToolboxData("<{0}:XmlView runat=server></{0}:XmlView>"),
XmlRoot(Namespace="XMLviewer")]
public class XmlView : Microsoft.SharePoint.WebPartPages.WebPart {
private const string defaultText = "XmlView";
private string text = defaultText;
private string xml = "";
private string xmllink = "";
private string xsl = "";
private string xsllink = "";
private Evidence evidence=null;
}


XmlWebPart & XmlView continued

Заказчику потребовалось использовать в xslt-преобразователе конструкцию <xsl:apply-templates select="document(file)..."/>
В стандартном XmlWebPart - работает. В моём XmlView - ни в какую.
При раскопках выяснилось, что загружать xsl нужно не конструкцией, которая сама напрашивается

XmlDocument xsl = new XmlDocument();
xsl.
LoadXml(xslScript); //в строке - текст xsl
XslTransform xslt =new XslTransform();
xslt.Load (new XmlNodeReader(xsl));
а немного поширше:

XmlDocument xsl = new XmlDocument();
xsl.
LoadXml(xslScript); //в строке - текст xsl
XslTransform xslt= new XslTransform();
XmlUrlResolver resolver=new XmlUrlResolver();
xslt. Load(new XmlNodeReader(xsl), resolver, XmlSecureResolver .CreateEvidenceForUrl(XslLink));
В .NET 2.0 опять по-другому:

XmlDocument xsl = new XmlDocument();
xsl.Load(
http://...test.xsl
);
XmlUrlResolver resolver=new XmlUrlResolver
();
resolver.Credentials =
CredentialCache
.DefaultNetworkCredentials;
XslCompiledTransform xslt= new XslCompiledTransform();
XsltSettings settings = new XsltSettings
();
settings.EnableDocumentFunction =
true
;
settings.EnableScript =
true
;
xslt.Load(
new XmlNodeReader
(xsl),settings,resolver);