вторник, 30 ноября 2010 г.

Одна из определяющих характеристик MVC

ИСТОЧНИК: "Professional ASP.NET MVC 1.0 By Rob Conery, Scott Hanselman, Phil Haack, Scott Guthrie"

Одной из определяющих характеристик шаблона MVC является строгое "разделение понятий". Модели (Models), Контроллеры (Controllers) и Представления (Views) имеют
четко определеные роли и обязанности, и они общаются между собой  по четко определенным правилам. Это улучшает тестируемость и повторное использование кода.
Когда клас контроллера решает вернуть НТML ответ обратно клиенту, он отвечает за точную передачу в шаблон представления всех данных необходимых для отображения этого ответа.
Шаблон представления (View template) никогда не должен выполнять каких либо  действий связанных с извлечением данных или с бизнес логикой.  Вместо этого Шаблон представления должен использоваться ТОЛЬКО для  отображения данных полученных от Контроллера.

пятница, 26 ноября 2010 г.

HTML helper methods - like Html.TextBox() - check the ModelState collection when rendering output. If
an error for the item exists, they render the user-entered value and a CSS error class.

вторник, 16 ноября 2010 г.

Автоматическое обновление Web-приложенния установленного на TabletPC (другой компьютер) через интернет.

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

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

Продолжение следует...

понедельник, 8 ноября 2010 г.

Как определить версию запущенного ( исполняемого ) приложения ( модуля )

'Получаем версию текущей исполняемой сборки
Dim sVer As String = System.Reflection.Assembly.GetExecutingAssembly.GetName().Version.ToString()
Dim realVersion As Version
Try
      realVersion = New Version(sVer)
Catch ex As Exception
      'если формат стоки для версии неправильный,будем считать что это нулевая версия      realVersion = New Version(0, 0, 0)
End Try
'главное значение версии (первая цифра)
Dim MajorVersion As String = realVersion.Major.ToString
'второстепенное значение версии (вторая цифра)
Dim MinorVersion As String = realVersion.Minor.ToString

четверг, 4 ноября 2010 г.

Рекомендации по именованию отдельных шаблонов представления

ИСТОЧНИК: "Professional ASP.NET MVC 1.0 By Rob Conery, Scott Hanselman, Phil Haack, Scott Guthrie"

Когда дело доходит до именования отдельных шаблонов представления рекомендуется давать шаблону тоже имя, что и метод действия, который был  вызван для визуализации. Например,   метод "Index" использует  представление  "Index" для отображения результата, и "Details" использует  представление "Details". Это   позволяет разработчику  легко определить, какой шаблон  представления связан с  методом действия.

Разработчикам нет необходимости точно указывать имя представления когда имя представдения совпадает с именем метода действия. Вместо этого мы можем использовать вспомогательный метод View() и передать в него в качестве параметра данные которые нам надо отобразить(без явного указания имени шаблона предсаления). И ASP.NET MVC автоматически определит что мы хотим использовать представление
\Views\[ControllerName]\[ActionName] для отображения результатов.

Было:
public ActionResult Index() {
var dinners = dinnerRepository.FindUpcomingDinners().ToList();
return View("Index", dinners);
}
Стало:
public ActionResult Index() {
var dinners = dinnerRepository.FindUpcomingDinners().ToList();
return View(dinners);
}

вторник, 2 ноября 2010 г.

Понимание маршрутизации для ASP.NET MVC

ИСТОЧНИК: "Professional ASP.NET MVC 1.0 By Rob Conery, Scott Hanselman, Phil Haack, Scott Guthrie"

Понимание маршрутизации для ASP.NET MVC

ASP.NET MVC содержит мощный механизм  роутинга URL,  позволяющий очень гибко  контролировать то, как URL работает  с классами контроллеров.  Это позволяет нам полностью настроить то ,  как ASP.NET MVC  выбирает класс контроллера ,какой метод вызывает, а также настроить различные способы с помощью которых переменные будут автоматически извлекаться из URL  и передаваться в методы в качестве параметров. Этот механизм  дает нам ту гибкость, которая позволит полностью оптимизировать сайт для Поисковой Отимизации , а также показывать любу стуктуру URL  какую мы хотим для приложения.

По умолчанию, новые проекты ASP.NET MVC  содержат в себе предустановленные настройки для URL роутинга. Этопозволяет легко начать работу с приложением без необходимости что либо настраивать.  Настройки правил для “URL маршрутизации по умолчанию”  можно найти в  файле Global.asax вашего ASP.NET MVC  приложения в классе “ Application ”. По умолчанию, правила маршрутизации для ASP.NET MVC  регистрируются в  методе “RegisterRoutes” этого класса.
“routes.MapRoute()” – регистрирует правило маршрутизации по умолчанию,  которое выстраивает соответствие входящего  URL  и классов котроллера, используя следующий формат URL : "/{controller}/{action}/{id}” – где “controller” это имя класса контроллера , экземпляр которого будет использоваться, “action” – это имя паблик метода который будет вызван, “id” – необязательный параметр, который может быть использован для переlачи парметра в метод из URL.  Третий параметр который подается в “MapRoute()” – это усановка набора  значений по умолчанию который используется для значения controller/action/id  в случае если они не присутствуют в URL  (Controller = “Home”,Action=”Index”, Id=””). Тоесть если мы ничего не введем в URL – эти значения будут подставленны автоматически.

Ниже приводится таблица, которая демонстрирует, как выстраиваются соответсвия между различными URL  и классами контроллера с их методаими, согдасно правилу маршрутизации “/{controllers}/{action}/{id}”.

Последние три строки показывают значения по умолчанию
 (Controller = Home, Action = Index, Id = ""). Так как метод “Index” зарегистрирован как имя действия по умолчанию, если таковое не указано, “/Dinners” и “/Home”  в URL   будут вызывать метод  Index() для соответствующих котроллеров. Так как контроллер “Home” зарегистрирован как контроллер по умолчанию , “/” в URL  будет создавать экземпляр класса HomeController и вызывать его метод  Index(). Если вам не нравятся правила маршрутизации по умолчанию – вы легко можете настроить их по своему усмотрению .

пятница, 15 октября 2010 г.

Определения свойств страницы для работы с данными хранимыми во ViewState

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

Public Property YourProperty() As List(Of PropertyType)
  Get
    If ViewState("YourProperty") Is Nothing Then
      ViewState("YourProperty") = New List(Of PropertyType)
    End If
    Return CType(ViewState("YourProperty"), List(Of PropertyType))
  End Get
  Set(ByVal value As List(Of PropertyType))
     ViewState("YourProperty") = value
  End Set
End Property


По аналогии можно создавать свойста нужного нам типа и с необходимой логикой. Данный подход избавляет от необходимости переустанавливать и перечитывания значения  переменной во ViewState на обработчиках событий страницы

пятница, 8 октября 2010 г.

Как обновить часть строки ( знaчения) в поле NTEXT

UPDATE [TABLE_NAME] SET
[FIELD_NAME] = REPLACE(CAST([FIELD_NAME] AS NVARCHAR(4000)),
'substring to be found for replacement',
'string that will replace the found substring')

Единственный момЭнт... Значение которое хранится в поле NTEXT не должно превышать 4000 символов.

четверг, 16 сентября 2010 г.

Холливарщикам ...

Давно надоели споры на тему что лучше "ASP.NET или PHP". Особенно надоели те люди, которые подобны"куликам в болоте" и не могут дальше своего болота что-либо увидеть...Причем таких бойцов предостаточно с обоих сторон.  На  все аргументы у них один контраргумент  - "мое болото круче, потому что оно мое!" ... Одним словом холливары в топку.
Вот,  замечательная и вдумчивая статья, на тему "ASP.NET или PHP".  Автор этой статьи -  молодец и умница. Побольше бы таких незамутненных взглядов.

PHP vs ASP.NET >>

среда, 15 сентября 2010 г.

Событийная модель страницы в ASP.NET

Четкое понимание событийной модели - это самое главное и основное умение которым вы должны обладать при использовании классической модели ASP.NET ( WebForms). Это скелет, устав, 10 заповедей - назовите это как хотите. Без знания и понимания данной модели создание эффективных веб-приложений невозможно.

Ниже два примера, показывающих  как незнание событийной модели может испортить вам жизнь. Суть примера такова - на странице находится ListView c с данными, и кнопка по счелчку на которую переходим на другую страницу. В обоих случаях - пользователь увидит наполненный ListView и перейдетнастраницу, но есть ньансы...

Main.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="main.aspx.vb" Inherits="main" %>
<html>
<head runat="server"><title></title></head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="Button1" runat="server" Text="Button" />
        <asp:ListView  ID="ListView1" runat="server">
            <LayoutTemplate>
                <ul>
                    <asp:PlaceHolder runat="server" ID="itemPlaceholder" />
                </ul>               
            </LayoutTemplate>
            <ItemTemplate>
                <li>
                    <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
                </li>
            </ItemTemplate>
        </asp:ListView>
    </div>
    </form>
</body>
</html>

Main.aspx.vb (вариант №1)

Partial Class main
    Inherits System.Web.UI.Page

    'биндинг ListView на Page_Load
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.Load
        ListView1.DataSource = GetData()
        ListView1.DataBind()
    End Sub

    'биндинг каждого элемента ListView
    Protected Sub ListView1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs) Handles ListView1.ItemDataBound
        CType(e.Item.FindControl("Label1"), Label).Text = CType(CType(e.Item, ListViewDataItem).DataItem, String)
    End Sub

    'переход на эту же страницу
    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Button1.Click
        Response.Redirect("states.aspx", True)
    End Sub

    'Функция для создания коллекции необходимой для наполнения ListView
    Public Function GetData() As List(Of String)
        Dim result As New List(Of String)
        For i As Integer = 0 To 100
            Dim labelName As String = "Label #" & i.ToString
            result.Add(labelName)
        Next
        Return result
    End Function

End Class


Main.aspx.vb (вариант №2)
Partial Class main
    Inherits System.Web.UI.Page


    'биндинг ListView на Page_PreRender
   
Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.PreRender
        ListView1.DataSource = GetData()
        ListView1.DataBind()
    End Sub


    'биндинг каждого элемента ListView
    Protected Sub ListView1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs) Handles ListView1.ItemDataBound
        CType(e.Item.FindControl("Label1"), Label).Text = CType(CType(e.Item, ListViewDataItem).DataItem, String)
    End Sub


    'переход на эту же страницу
    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Button1.Click
        Response.Redirect("main.aspx", True)
    End Sub


    'Функция для создания коллекции необходимой для наполнения ListView
    Public Function GetData() As List(Of String)
        Dim result As New List(Of String)
        For i As Integer = 0 To 100
            Dim labelName As String = "Label #" & i.ToString
            result.Add(labelName)
        Next
        Return result
    End Function


End Class


Разбор Полетов

В обоих случаях ListView будет наполнен и пользователь сможет перейти на другую страницу ( в нашем случае - та же самая страница). Теперь важно понимать событийную модель, чтобы увидеть в чем проблема для варианта №1.

В первом варианте биндинг ListView проводится на обработчике события Page_Load.
Переход на страницу осуществляется на событии кнопки Click.

Что происходит по счелчку на кнопку? По счелчку страница уходит на сервер, где начинается ее обработка. Согласно событийной модели,   сначала отработается событие Load ( а вместе с этим выполнится код описанный в обработчике этого события Page_Load). Только после этого отработается отложенное событие, которым является Click  нашей кнопки. И только после этого произойдет переход на другую страницу.
Таким образом биндинг ListView будет происходить все время.

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

Во втором случае биндинг ListView проводится на обработчике события Page_PreRender
Переход на страницу осуществляется на событии кнопки Click.

Во втором  случае все проиходит нормально. Событие PreRender возникает после обработки отложенных событий ( событие Click  нашей кнопки).  Таким образом,  биндинг ListView не будет происходить лишний раз.  По счелчку на кнопку пользователь сразу перейдет на страницу.

Понимание событийной модели очень важно.

Ссылка на МSDNовский ресурс который замечательно описывает событийную модель страницы. >>

суббота, 11 сентября 2010 г.

ListView vs. Web User Control для отображения списков "Тяжелых" сущностей

Теория

Задача.

Необходимо отображать и редактировать большой  список сущностей. Без пейджинга. Сущности редактируются прямо в списке.   Каждая сущность включает  в себя "тяжелые" ("долгоиграющие") запросы. Под этими запросами я подразумеваю те запросы, которые отрабатываются достаточно долго, ресурсоемки и результаты которых кешировать или не возможно или же не выгодно. Например включает в себя список картинок, которые хранатся в базе в оригинальном размере и при извлечении преобразуюются в меньший размер. Для отображения картинок используется хендлер (тоесть картинки не сохраняются в файловой срситеме). Таким образом, по условию, сущность которая отображается в качестве элемента списка составная и требует определенного количества внутренних запросов для своего формирования. Кешировать даные результаты, будь то ViewState или Session возможно но ресусроемко.

Варианты Реализации.

Вариант Первый.
Самый первый и классический вариант это использование ListView (или GridView. Я предпочитаю первый вариантб так как это позволяет полностью контролировать выходной HTML). Недостатком использования  ListView является то, что при любом событии ListView (будь то перевод элемента в состояние редактирования или отменя редактирования, любой PostBack со сороны ListView) необходимо проводить полный перебинд всего ListView. Тоесть,  при отсутствии возможности кеширования результатов выборки, это опять вычитка из базы всех связанных данных для кажого элемента списка , биндинг каждого элемента и тд.
При отображении скажем трехсот  элементов , простой перевод одного элемента списка  в режим редактирования потребует провести 300 на Х запросов к базе ( где Х - количество внутренних запросов для одного элемента списка). Такой подход будет очень расстравать пользователя, который ожидает мгновенной реакции на такое, как ему кажется, простое действие.

Как вариант, это кешировать данные первоночальной выборки (ViewState или Session), но в любом случае, происходит перебинд всех элементов списка. В случае же, когда на ItemDataBound происходит вычитка всех картинок для сущности и "Тяжелые" операции все равно происходят- это не является оптимальным решением. Все равно медленно... И даже если это исключить, все равно придется при изменении сущности либо перечитывать всю коллекцию, либо изменять закешированную коллекцию. При любых вырантах работы с  ListView - происходит перебинд все эелементов списка.

Решением могло бы стать наличие таких возможностей как перебинд и перерендер только того элемента коллекции с которым идет работа.  Для перерендера только  активного элемента списка ListView решением могло бы быть заключение каждого элемента списка в Update Panel. Но к сожалению ListView имеет различные темплейты для каждого из режимов элемента (отображене, редактирование и тд.) и декларативно обьединить их в одну Update Panel не представляется возможным.  В Update Panel  мы можем положить только весь ListView целиком. Тоесть получаем те же самые проблемы как и при отсутствии Update Panel.

Задача выкристализовывается - "Биндить и рендерить только то, что изменяем".

Вариант Второй.
Для отображения элемента списка мы создаем User Web Controls. Который представляет собой FormView обернутый в Update Panel. И это позволяет рендерить  только тот элемент с которым мы работаем. Так как мы рендерим только один активный элемент, нам нет необходимости биндить другие.  Мы биндим только один!

Производительность.
Опыты показали, что использованние ListView для первично отображения данных (списка сущностей) дает более быстрые результаты, нежели динамическое добавление User Web Controls для тех же целей. Но дальнейшее использование  User Web Controls для редактирования сущности в списке дает лучшую скорость реакции. Я бы скадзал - значительно лучшую ( Так как выборка и биндинг  производится только для одной, текущей сущности). Если же отключить ViewState для контролов отображающие статические данные - то производитьельность увеличится как для первого так и для второго подходов.

Вывод.
Использование ListView + кеширование данных выборки (при условии отсутствия некешируемых элементов и долгоиграющих запросов для наполнения каждого элемента списка) удобнее, проще и быстрее нежели динамическое добавление User Web Controls.
НО! Если возникает ситуация, когда для наполнения каждой сущности используются некешируеммые элементы и долгоиграющие запросы тот выгоднее и быстрее использовать динамически добавляемые User Web Controls

Практика
Структура проекта

четверг, 9 сентября 2010 г.

Требования к системе для .NET Framework

Тут вот камрад интересную ссылочку подкинул с MSDN. Документик содержит
требования к оборудованию, операционной системе и программному обеспечению для платформы .NET Framework. Очень интересненько... А вы думали NET Framework 4 белый и пушистый, а ему вишь - надо 1 ГГц проца и 512 метров оперативки. и забудте про  Windows XP Tablet PC Edition...

http://msdn.microsoft.com/ru-ru/library/8z6watww.aspx

среда, 8 сентября 2010 г.

IIS6 , II7 и печальные размышления о современниках.

Давеча переносил приложение с одного сервера на другой. Соответственно  с IIS6 на IIS7.  IIS7 - понравился, немножко непривычно после IIS6 - но в целом позитвное впечатление.
А теперь о печалном...
После успешного переноса, решил проверить как все работает. Запустил приложение, проверил определенную фунциональность и тут нате:

"Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached."

Ну думаю все понятно - не закрытые соединения к базе. Проверяю соединения к базе - 100 активных соединений!!!  Быстренько вспомнил что делал на сайте и сориентировался в коде что и где... И действительно, в 15(!!!) местах соединение не закрывается. Код не мой, писал подчиненный. И вроде не дурак, может давать хороши и стабильные решения.. НО ТАКОЕ...
Вопрос к  космосу - "ДОКОЛЕ БУДЕТ ПРОЦВЕТАТЬ ТАКОЕ РАЗГИЛЬДЯЙСТВО И БЕЗАЛАБЕРНОСТЬ?!"

А теперь о IIS7 - он поймал эту ошибку. А IIS6 хавал и проглатывал, в результате чего страдала производительность. Такие дела.

среда, 1 сентября 2010 г.

TextBoxWatermarkExtender и UpdatePanel

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

Например.
...
<asp:TextBox   ID="txtLogin" runat="server"></asp:TextBox>
<cc1:TextBoxWatermarkExtender ID="TBWERFALogNumber" runat="server"

TargetControlID="txtLogin"
WatermarkText="Type Login Here" />
....

Теперь при рендере у нас будет текстовое поле внутри которго будет сообщение "Type Login Here". При наведении фокуса на это поле, сообщение пропадает и у нас есть возможность ввести все что нам надо. Если ничего не ввели - то это сообщение появляется опять  при потере фокуса текстовым полем.

После постбека спокойно обращаемся к TextBox не задумываясь о TextBoxWatermarkExtender. Если ничего не было введено, значение TextBox.Text будет пустым. TextBoxWatermarkExtender не окажет никакого влияния на TextBox.

Ситуация координально меняетеся если мы обернем наш  контент в UpdatePanel.
....
<asp:UpdatePanel ID="upSH" runat="server">
<ContentTemplate>
...
<asp:TextBox ID="txtLogin" runat="server"></asp:TextBox>

<cc1:TextBoxWatermarkExtender ID="TBWELogin" runat="server"
TargetControlID="txtLogin"
WatermarkText="Type Login Here" />
...
</ContentTemplate>

</asp:UpdatePanel>
...


Теперь при постбеке, TextBox.Text  всегда будет содержать значение того,  что было написано в нем. Инными словами, если мы ничего не ввели в TextBox, значение TextBox.Text будет равно "Type Login Here" (так как этозначение было установленно туда контролом TextBoxWatermarkExtender ).

Теперь для того чтобы получить корректное значение введенных данных для TextBox , на постбеке необходимо сравнивать значение присутствующее в TextBox со значением  установленным для TextBoxWatermarkExtender.

...
Dim result as String = String.Empty
If txtLogin.Text.Trim <> String.Empty Then
    If Not txtBudgetCost.Text.Trim.Equals(TBWELogin.WatermarkText.Trim) Then
       result = txtLogin.Text.Trim
    End If
End If
....

После этого переменная result будет содержать корректные данные.

вторник, 17 августа 2010 г.

Progress Info в любом месте экрана

Задача.
Отоброжать информацию пользователю о том что страница выполняет действия и процесс идет. Дабы пользователь не нервничал и приятно любовался либо сообщением либо симпатичной анимацией.
Решение.
Комбинация из UpdatePanel, UpdateProgress и AlwaysVisibleControlExtender.

<asp:UpdatePanel ID="UpdatePanel1" runat="server">

  <ContentTemplate>
    <asp:UpdateProgress ID="UpdateProgress1" EnableViewState="false"    AssociatedUpdatePanelID="UpdatePanel1" runat="server">
       <ProgressTemplate>
           <img id="imgLoading" runat="server" src="LOADING.gif" alt="" />
      </ProgressTemplate>
    </asp:UpdateProgress>
    <cc1:AlwaysVisibleControlExtender ID="AlwaysVisibleControlExtender1" runat="server"
     TargetControlID="imgLoading"
     VerticalSide="Top"
     VerticalOffset="10"
     HorizontalSide="Center"
     HorizontalOffset="10"
     ScrollEffectDuration=".1"/>


.....


  </ContentTemplate>
</asp:UpdatePanel>

В результате картинка LOADING.gif будет показываться вверху экрана при каждом постбеке  формы обернутой в UpdatePanel

четверг, 12 августа 2010 г.

Реакция формы на Enter

Гораздо удобнее при поиске или логине пользоваться кнокой Enter вместо того чтобы отрывать руки от клавиатуры и тыцать мышкой. Как это реализовать? Просто.
Если у вас простая форма с одной кнопкой - то по нажатию Enter, атоматически сработает эта кнопка. Вообще - автоматически срабатывает первая по порядку кнопка в форме. Если нопка не перваяб тогда используем свойство defaultbutton для <form> или <asp:panel>. Тоесть устанавливаем либо для формы, либо оборачиваем нужную на группу в <asp:panel> и устанавливаем необходимое нам свойство.

<form defaultbutton=“btnLogin” runat=“server”>
   <asp:textbox id=“txtLogin” runat=“server”/>
   <asp:textbox id=“txtPassword” runat=“server”/>
   <asp:button id=“btnLogin” text=“Login” runat=“server”/>
</form>
или
<form runat=“server”>
  <asp:panel defaultbutton=“btnSearch”  runat=“server”>
     <asp:textbox id=“txtSearch” runat=“server”/>
     <asp:button id=“btnSearch” runat=“server”/>
  </asp:panel>
</form>

пятница, 30 июля 2010 г.

Рекомендации по управлению состоянием ASP.NET

ViewState или Состояние Сесси?
Когда и для чего использовать Сookie?
Для чего Состояние Приложения (HttpApplicationState)?
Замечатьельная статья из MSDN, ответит на многие вопросы и даст обзор испоkьзования разлbчных механизмов для достижения одной цели - отслеживать состояние в промежутках между круговыми путями сервера.

http://msdn.microsoft.com/ru-ru/library/z1hkazw7(v=VS.90).aspx

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

вторник, 27 июля 2010 г.

Использование единого URL для различных поведенческих моделей одной формы в MVC

Помни, Товарищ!
Использование единого URL для различных поведенческих моделей одной формы в MVC (URL то один, но в зависимости от типа HTTP запроса - вызываются различные методы контроллера и различные вьюшки) избавляет от пробелем с закладками на данную страницу и отпроблемы повторной пересылки редактируемой формы.

Оригинал
You might ask – why are we using a single URL and differentiating its behavior via the HTTP verb? Why not just have two separate URLs to handle loading and saving edit changes? For example: /Dinners/Edit/[id] to display the initial form and /Dinners/Save/[id] to handle the form post to save it?
The downside with publishing two separate URLs is that in cases where we post to /Dinners/Save/2, and then need to redisplay the HTML form because of an input error, the end-user will end up having the /Dinners/Save/2 URL in their browser’s address bar (since that was the URL the form posted to). If the end-user bookmarks this redisplayed page to their browser favorites list, or copy/pastes the URL and emails it to a friend, they will end up saving a URL that won’t work in the future (since that URL depends on post values).
By exposing a single URL (like: /Dinners/Edit/[id]) and differentiating the processing of it by HTTP verb, it is safe for end-users to bookmark the edit page and/or send the URL to others.

Источник
Professional ASP.NET MVC 1.0
By Rob Conery, Scott Hanselman, Phil Haack, Scott Guthrie

понедельник, 26 июля 2010 г.

LINQ2SQL и валидация данных.

Помни, Товарищ!
LINQ2SQL по умолчанию предоставляет валидацию данных на уровне схемы, сгенерированной на основе базы данных. Тоесть, если в таблице присутствует поле типа 'integer', в сгенерированной схеме это поле тоже будет обозначено как 'integer'. И всякие попытки впихнуть в это поле что либо, отдичное от 'integer' - вызовет ошибку компиляции. Что это нам дает? Правильно, базовую защиту данных от "SQL иньекций" на уровне схемы.

пятница, 23 июля 2010 г.

С# или VB.NET?

Должен владеть обоими языками.
НЕ ОБСУЖДАЕТСЯ.

LINQ2SQL and Transaction

Помни, Товарищ!
LINQ2SQL автоматически оборачивает все измененяи в базе данных в транзакцию!
Что бы ты не насчелкал и не на изменял - все это призойдет в транзакции на SubmitChanges.

Оригинал:
LINQ to SQL automatically wraps all changes in a database transaction – so either all changes happen or none of them do when our куpository saves:
DinnerRepository dinnerRepository = new DinnerRepository();
// Create First Dinner
Dinner newDinner1 = new Dinner();
newDinner1.Title = "Dinner with Scott";
newDinner1.HostedBy = "ScotGu";
newDinner1.ContactPhone = "425-703-8072";


// Create Second Dinner
Dinner newDinner2 = new Dinner();
newDinner2.Title = "Dinner with Bill";
newDinner2.HostedBy = "BillG";
newDinner2.ContactPhone = "425-555-5151";


// Add Dinners to Repository
dinnerRepository.Add(newDinner1);
dinnerRepository.Add(newDinner2);


// Persist Changes
dinnerRepository.Save();

Источник:
Professional ASP.NET MVC 1.0
By Rob Conery, Scott Hanselman, Phil Haack, Scott Guthrie

И сразу вопрос.. А если мне надо провести два SubmitChanges в одной транзакции?