2016-05-25 4 views
1

Я обновляюсь с sitecore 7.2 до sitecore 8.1. У меня есть 5-летний опыт работы с веб-формами, но всего на несколько месяцев я был заинтересован в MVC. В дополнение к обновлению до 8.1 мой босс хочет перейти от веб-форм к MVC. У моей компании несколько сложная форма логики в Sitecore с Asp.Net Web Forms, где каждое поле формы является собственным Sublayout (User Control). Это позволяет редактору содержимого включать, а не включать и изменять порядок полей формы на основе требований, данных бизнесом. Вот как я сделать это в Web Forms (BTW мы также используем GlassMapper): Форма Markup фрагмент кода:Sitecore: преобразование динамических форм из веб-форм в MVC

<div id="formInputSection" runat="server"> 
    <div id="fields"> 
     <p class="required italic <%=reqFieldTextColor %>"> 
      <sc:Text ID="formReqFields" Field="Required Fields Text" runat="server" ClientIDMode="Static" DataSource="<%#lpOptions.Paths.FullPath %>" /> 
     </p> 

     <asp:UpdatePanel ID="formUpdatePanel" runat="server"> 
      <ContentTemplate> 
       <asp:Panel ID="formPanel" runat="server"> 
        <asp:ValidationSummary ID="valSumFormSubmit" runat="server" DisplayMode="BulletList" ValidationGroup="formSubmit" CssClass="errorMsg" /> 
        <div> 
         <sc:Placeholder ID="FormFieldsSect" Key="v2_ph_form_fields_col1" runat="server" /> 
        </div> 
       </asp:Panel> 
      </ContentTemplate> 
     </asp:UpdatePanel> 
    </div>   

    <div id="form_action_submit" runat="server" class="form-action submit"> 
     <asp:LinkButton ID="btnSubmitForm1" CssClass="form-input submit white" OnClientClick="ValidateAndDisableButton();" OnClick="submit_Click" UseSubmitBehavior="false" runat="server" ClientIDMode="Static" Text="<%#Model.Form_Submit_Text %>" ValidationGroup="formSubmit" /> 
     <sc:Link ID="pgEditorFormSubmit1" Field="Editor Confirmation Link" CssClass="form-input submit white" runat="server" DataSource="<%#lpOptions.Paths.FullPath %>" Visible="false"> 
      <sc:Text Field="Form Submit Text" ID="pgEditorSubmitText1" runat="server" ClientIDMode="Static" DataSource="<%#lpOptions.Paths.FullPath %>" Visible="false" /> 
     </sc:Link> 
    </div> 

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

Следующая пометка для одного из основных подрайонов поля. Я буду использовать ПгвЬЫате ...

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="FirstNameField.ascx.cs" Inherits="MyNamespace.FirstName" %> 
    <%@ Register TagPrefix="sc" Namespace="Sitecore.Web.UI.WebControls" Assembly="Sitecore.Kernel" %> 
    <div class="clearfix form-input field text <%=LabelStyle %>"> 
     <asp:Label ID="Label1" AssociatedControlID="txtFirstName" Text="<%#Editable(x => x.First_Name) %>" runat="server" /> 
     <asp:TextBox ID="txtFirstName" runat="server" ClientIDMode="Static" type="text"></asp:TextBox> 
     <asp:RequiredFieldValidator ID="validFirstName" runat="server" ControlToValidate="txtFirstName" ErrorMessage="<%#Model.First_Name_Required %>" 
      Enabled="true" ValidationGroup="formSubmit" Display="None"></asp:RequiredFieldValidator>  
    </div> 
    <br /> 

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

public partial class FirstName : InheritsFromGlassUserControl<FormFields> 
{ 
    protected override void Page_Load(object sender, EventArgs e) 
    { 
     if (this.Visible == true) 
     {     
      SitecoreContext context = new SitecoreContext(); 
      Model = context.GetItem<FormFields>(Sitecore.Context.Database.GetItem(((Sublayout)Parent).DataSource).ID.Guid); 
//ls is an object that we grab from session to update and put back into session 
//to handle cross user control communication and such 
      ls = GetSession();  
      LabelStyle = ls.MergeLabels ? "merge-label" : string.Empty; 
      if (!string.IsNullOrWhiteSpace(txtFirstName.Text)) 
      { 
       ls.CurrentLead.FirstName = txtFirstName.Text; 
      } 
      else 
      { 
       if (!IsPostBack) 
       { 
        if (!string.IsNullOrWhiteSpace(ls.CurrentLead.FirstName) && !ls.IsReferralForm) 
         txtFirstName.Text = ls.CurrentLead.FirstName; 
       } 
      }  
//Put updated values in "ls" back into session for the next field to update, with its input   
      SessionDetails = ls; 
      SetRenderingParameters(); 
     } 
     this.DataBind(); 
    } 
} 

вопрос у меня есть что было бы лучшим способом реализовать такое решение в MVC? У меня нет большого опыта работы в MVC, а не просто для создания неаккуратного решения, которое я хотел бы знать, если бы у кого-то был лучший пример практики того, как бы они (реализовали) автономные поля формы с учетом BeginForm () в сообщениях MVC к модели, но «модель» стекломастера несет ответственность за содержимое сообщения метки поля и поля, которое заполнено из файла sitecore. Мне не удалось заставить обе модели сосуществовать в одном файле cshtml. Я знаю, что это сложно, но концепция полей plug and play - очень ценное решение для бизнеса. И я понял, что работает для меня в Web Forms; просто имея проблемы, обволакивая мою голову, делая это в MVC.

+0

Насколько сложна не ваши требования к форме? Вы считали, что вместо этого используете [Web Forms For Marketers module] (https://doc.sitecore.net/web_forms_for_marketers)? – jammykam

+0

Они довольно сложны, но мы собираемся создать API для тяжелого подъема. Таким образом, наши формы будут отправлять данные в API и обновлять ExternalUser в sitecore, и API будет обрабатывать отправку контактной информации в Eloqua и наш CRM. Ожидается обновление до WFFM, и я жду этого, потому что каждый раз, когда они обновляют его, многие изменения касаются того, как материал ссылается на SC. И, начиная с 7.2 до 8.1, я уже знаю, что я собираюсь изучить новые соглашения об именах и местоположения для вещей. –

+0

API также, вероятно, будет обрабатывать ситуации, в которых подана форма для регистрации вебинара, в этом случае он зарегистрирует контакт для веб-семинар Adobe или Citrix, одновременно отправляя Eloqua для подсчета очков и CRM для других целей. –

ответ

0

ОК, поэтому на прошлой неделе я решил ответить на этот вопрос, и я не хотел его публиковать, пока не успел подробно объяснить. Так, как я сказал в вопросе, наши формы - это просто заполнители заполнителей, и мы повторно используем те же пользовательские элементы поля формы (подслои) во всех наших формах. Поэтому в MVC я хочу нечто подобное. Итак, вы видите в примере этой формы, у нас есть только один заполнитель, такой как версия WebForms. * Обратите внимание на ссылку baseformhelper.js для последующего использования.

@using Sitecore.Mvc 
@using Sitecore.Mvc.Presentation 

@inherits Glass.Mapper.Sc.Web.Mvc.GlassView<Contact_Form> 
@{ 

} 
@using (Html.BeginRouteForm(Sitecore.Mvc.Configuration.MvcSettings.SitecoreRouteName, 
    FormMethod.Post)) 
{ 
    @Html.Sitecore().FormHandler("ContactForm", "SubmitContact") 
    <div class="bottom-form-wrapper green-bg"> 
     <p class="form-title white">@Editable(x => x.Form_Headline_Text)</p> 
     <p class="required white italic">@Editable(x => x.Required_Fields_Text)</p> 
     <div id="divForm" class="twocol-bottom-form"> 
      @Html.Sitecore().Placeholder("v2_ph_formfields_col1") 
     </div> 
    <div class="clearfix"></div> 
     <div id="form_action_submit" class="form-action submit"> 
      <input type="submit" id="lnkSubmitForm1" class="form-input submit red-bg white" value="@Editable(x => x.Submit_Button_Text)" /> 
     </div> 
    </div><!--end form-wrapper-->  
<script type="text/javascript" src="~/scripts/Base-LP/BaseFormHelper.js" ></script > 
} 
... 

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

//Contact model that inherits from glass mapper class 
public class Contact : FormFields 
{ 
    #region Properties 

    [Required] 
    public string FirstName { get; set; } 

    [Required] 
    public string LastName { get; set; } 
... 

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

@using Sitecore.Mvc 
@using Sitecore.Mvc.Presentation 
@model Models.Contact 
@{ 
//First_Name property comes from Contact class 
//FirstName property comes form FormFields Glass Mapper Class 
} 

<div id="form_input_firstname" class="clearfix form-input text"> 
    @Html.LabelFor(x => x.FirstName, Model.First_Name) 
    @Html.TextBoxFor(x => x.FirstName, new { id = "txtFirstName" }) 
    @Html.ValidationMessageFor(x => x.FirstName, null, new { id = "validFirstName" }) 
</div> 
<script type="text/javascript" async> 
//FirstName Validation Message 
function FirstNameValidationMsg() { 
    var myMsgNode = document.getElementById('validFirstName'); 
    //Find span that contains validation message 
    if (myMsgNode.childElementCount > 0) 
     myMsgNode.children[0].innerHTML = '@Model.First_Name_Required';//Overwrite validation with dynamic message from sitecore 
} 
</script> 

Теперь, в веб-формы я использовал "жерех: RequiredFieldValdidatior", и в MVC Я использую комбинацию jquery.validate с Foolproof Validation для MVC. В первом поле имени мне не нужна проверка FoolProof, но я добавил строку в функцию onError в файле jquery.validate.unobtrusive.js, так что sitecore имеет окончательное мнение о том, каково будет сообщение проверки.

function onError(error, inputElement) { // 'this' is the form element 
    var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"), 
     replaceAttrValue = container.attr("data-valmsg-replace"), 
     replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null; 

    container.removeClass("field-validation-valid").addClass("field-validation-error"); 
    error.data("unobtrusiveContainer", container); 

    if (replace) { 
     container.empty(); 
     error.removeClass("input-validation-error").appendTo(container); 
    } 
    else { 
     error.hide(); 
    } 
    //Call custom function to overwrite validation messages 
    if (typeof setValidationMessages == 'function') 
     setValidationMessages(inputElement[0]); 
} 

Функция "setValidationMesages" находится в baseformhelper.js. Если он недоступен, он не будет прерывать jquery.validate, но если он есть, он выведет подтверждение для каждого поля формы, добавленного в презентацию. Используя ту же «если функция доступна, назовите ее» логикой.

//Base Form Helper 
//Perform important form related functions and calculations here... 

//Attempt to call function responsible for updating validation message with value from sitecore for each form field 
//if not available, nothing will break 
function setValidationMessages(element) { 
switch (element.id) 
{ 
    case "txtFirstName": 
     if (typeof FirstNameValidationMsg == 'function') { 
      FirstNameValidationMsg(); 
     } 
     break; 
    case "txtLastName": 
     if (typeof LastNameValidationMsg == 'function') { 
      LastNameValidationMsg(); 
     } 
     break; 
... 

Так в Sitecore, я могу добавить свои динамические поля в мой заполнитель, они обновляют модели контакта с их значением, при отображении их уникальное сообщения проверки. Когда я отправляю свой контроллер, все значения полей, которые я решил добавить в презентацию, присутствуют, и я могу сделать с ними то, что хочу. Да, проблема решена. До следующего раза ...

public class ContactFormController : Controller 
    { 
     [HttpPost] 
     public ActionResult SubmitContact(Models.Contact postedContact) 
     {    
      if(ModelState.IsValid) 
      { 
       //Do something like call to an API to post to Eloqua, CRM, or update Sitecore Contact for DMS/Experience Reports 
      } 
      else 
      { 
       //Do something else like log information about the contact so you know who tried to fill out your form even though your form submission logic is screwed up. 
      } 
     } 
... 
+0

Я просто хотел прокомментировать, что это ответ на мой собственный вопрос, поэтому я не совсем уверен, что я делаю что-то, что считается «нет-нет». Как я уже сказал в этом вопросе, я хотел бы получить ответы на более эффективные методы, потому что я знаю, что мое собственное решение может считаться «неряшливым» по некоторым стандартам. –

Смежные вопросы