Integração de um suplemento de evento corporativo com o SharePoint
O exemplo BusinessApps.CorporateEventsApp mostra como implementar um sistema centralizado de gerenciamento de eventos corporativos como um suplemento hospedado pelo provedor que se integra aos seus aplicativos de linha de negócios (LOB) existentes.
Mais especificamente, o exemplo BusinessApps.CorporateEventsApp mostra como implementar um aplicativo da Web ASP.NET que interaja com o SharePoint como um armazenamento de dados para entidades de linha de negócios (LOB). Ele também mostra como implementar várias etapas em uma tarefa comercial complexa com um único suplemento hospedado pelo provedor.
Este aplicativo de amostra implementa um sistema de gerenciamento centralizado que consiste em entidades do SharePoint (listas e tipos de conteúdo). Para cada novo tipo de conteúdo, ele cria entidades de linha de negócios (LOB) correspondentes em um aplicativo da web ASP.NET. Os componentes do aplicativo da web são executados como partes do suplemento hospedado remotamente na interface do SharePoint e também como páginas sendo executadas totalmente no host da web remoto. O suplemento substitui a página de boas-vindas padrão do seu site do SharePoint para que ele possa apresentar uma interface de marca personalizada na página inicial do site.
Usando o exemplo BusinessApps.CorporateEventsApp
Configurar o exemplo
Quando você inicia o aplicativo de exemplo BusinessApps.CorporateEventsApp, a página inicial fornece uma opção para você configurar o exemplo. Ele também mostra a você vários recursos para obter mais informações.
Ao escolher Iniciar configuração, você acessa a página Configurações, conforme mostrado na figura a seguir. Quando você escolhe Inicializar o armazenamento de dados na página Configuração, o exemplo implanta as entidades do SharePoint e os dados do exemplo que dão suporte ao exemplo.
Depois de inicializar o armazenamento de dados, você pode voltar ao seu site para ver uma nova página de boas-vindas (a página EventsHome.aspx), que é preenchida por duas web parts que o suplemento implantou, como mostra a figura a seguir. Na coluna da esquerda, você vê as quatro novas listas instaladas pelo suplemento. A lista de Eventos Corporativos é preenchida com dados de amostra.
Cada web part contém links para cada um dos eventos exibidos, onde você pode ver os detalhes do evento. Quando você escolhe um link, a página detalhes do evento é executada separadamente no host remoto, conforme mostrado na figura a seguir. Você pode escolher Voltar ao Site na página para retornar ao site do SharePoint e registrar-se para o evento.
A página de registro é executada separadamente no host remoto e contém um link para o site do host do SharePoint. Quando você terminar de se inscrever no evento, seu nome aparecerá na recém-instalada lista de Registro do Evento.
Arquivo Models/DataInitializer.cs
O arquivo Models/DataInitializer.cs contém o código que é executado quando você escolhe esse botão. O código nesse arquivo cria e implanta quatro novas listas do SharePoint, junto com quatro tipos de conteúdo correspondentes:
- Eventos corporativos
- Registro de Eventos
- Oradores do Evento
- Sessões do Evento
O código nesse arquivo usa um método semelhante ao usado no exemplo Core.ModifyPages para adicionar uma página personalizada ao site.
// Create default wiki page.
web.AddWikiPage("Site Pages", "EventsHome.aspx");
AddWikiPage is an extension method from the Core.DevPnPCore project to add a new page to the site. This new page also becomes the new WelcomePage for the site. It also prepares to add the web parts to this page.
var welcomePage = "SitePages/EventsHome.aspx";
var serverRelativeUrl = UrlUtility.Combine(web.ServerRelativeUrl, welcomePage);
File webPartPage = web.GetFileByServerRelativeUrl(serverRelativeUrl);
if (webPartPage == null) {
return;
}
web.Context.Load(webPartPage);
web.Context.Load(webPartPage.ListItemAllFields);
web.Context.Load(web.RootFolder);
web.Context.ExecuteQuery();
web.RootFolder.WelcomePage = welcomePage;
web.RootFolder.Update();
web.Context.ExecuteQuery();
O arquivo Models\DataInitializer.cs também define o XML para as duas web parts exibidas na nova página de boas-vindas e, em seguida, adiciona cada uma delas à página. Os exemplos a seguir mostram como isso funciona para a web part de Eventos em Destaque.
Definir XML de web part
var webPart1 = new WebPartEntity(){
WebPartXml = @"<webParts>
<webPart xmlns='http://schemas.microsoft.com/WebPart/v3'>
<metaData>
<type name='Microsoft.SharePoint.WebPartPages.ClientWebPart, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' />
<importErrorMessage>Cannot import this web part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name='Description' type='string'>Displays featured events</property>
<property name='FeatureId' type='System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'>3a6d7f41-2de8-4e69-b4b4-0325bd56b32c</property>
<property name='Title' type='string'>Featured Events</property>
<property name='ProductWebId' type='System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'>12ae648f-27db-4a97-9c63-37155d3ace1e</property>
<property name='WebPartName' type='string'>FeaturedEvents</property>
<property name='ProductId' type='System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'>3a6d7f41-2de8-4e69-b4b4-0325bd56b32b</property>
<property name='ChromeState' type='chromestate'>Normal</property>
</properties>
</data>
</webPart>
</webParts>",
WebPartIndex = 0,
WebPartTitle = "Featured Events",
WebPartZone = "Rich Content"
};
Adicionar as web parts à página
var limitedWebPartManager = webPartPage.GetLimitedWebPartManager(Microsoft.SharePoint.Client.WebParts.PersonalizationScope.Shared);
web.Context.Load(limitedWebPartManager.WebParts);
web.Context.ExecuteQuery();
for (var i = 0; i < limitedWebPartManager.WebParts.Count; i++) {
limitedWebPartManager.WebParts[i].DeleteWebPart();
}
web.Context.ExecuteQuery();
var oWebPartDefinition1 = limitedWebPartManager.ImportWebPart(webPart1.WebPartXml);
var oWebPartDefinition2 = limitedWebPartManager.ImportWebPart(webPart2.WebPartXml);
var wpdNew1 = limitedWebPartManager.AddWebPart(oWebPartDefinition1.WebPart, webPart1.WebPartZone, webPart1.WebPartIndex);
var wpdNew2 = limitedWebPartManager.AddWebPart(oWebPartDefinition2.WebPart, webPart2.WebPartZone, webPart2.WebPartIndex);
web.Context.Load(wpdNew1);
web.Context.Load(wpdNew2);
web.Context.ExecuteQuery();
No diretório de modelos do seu projeto da web, você notará que este aplicativo web ASP.NET MVC contém quatro nomes de classe que correspondem às listas e tipos de conteúdo que o suplemento instalou:
- Event.cs (Eventos Corporativos)
- Registration.cs (Registro do Evento)
- Session.cs (Sessões do Evento)
- Speaker.cs (Oradores do Evento)
Essas quatro classes e seus tipos de conteúdo correspondentes do SharePoint juntos compõem as quatro entidades de linha de negócios (LOB) usadas neste suplemento.
O arquivo DataInitializer.cs inclui dados de amostra para a lista Eventos Corporativos, criando objetos de Evento de exemplo que correspondem ao tipo de conteúdo Eventos Corporativos e que o suplemento adiciona à lista Eventos Corporativos.
Quando você se registra em um evento, o suplemento cria um objeto Registro que corresponde ao tipo de conteúdo Registro do Evento e que o suplemento adiciona à lista Registro do Evento. O exemplo ainda não implementou totalmente os objetos Sessão e Orador, portanto, o suplemento atualmente não funciona com esses objetos.
A tabela a seguir lista as propriedades que precisam ser implementadas pelas classes que herdam da classe abstrata BaseListItem.
Member | Descrição |
---|---|
ContentTypeName | Obtém o tipo de conteúdo associado ao item. Se for nulo, o tipo padrão de conteúdo da biblioteca será atribuído ao item quando você salvá-lo. |
FieldInternalNames | Uma lista de nomes de campos que podem ser armazenados em cache para melhorar o desempenho quando usados para verificar dados de campo antes de salvar. |
ListTitle | Obtém o título da lista (diferencia maiúsculas de minúsculas). |
A tabela a seguir lista os métodos que devem ser implementados pelas classes que herdam da classe abstrata BaseListItem. Esses métodos retornam parâmetros que devem ser configurados para tipos blittable, para que possam ser usados em várias plataformas.
Método | Descrição |
---|---|
ReadProperties(ListItem) | Lê as propriedades do objeto ListItem usando os métodos BaseGet e BaseGetEnum e as atribui às propriedades da subclasse. |
SetProperties(ListItem) | Define propriedades no objeto ListItem usando os métodos BaseSet e BaseSetTaxonomyField da classe abstrata. |
A tabela a seguir lista os métodos auxiliares da classe BaseListItem que as subclasses precisam para implementar os métodos ReadProperties e SetProperties.
Método Auxiliar | Descrição |
---|---|
BaseGet(item ListItem, cadeia de caracteres internalName) | Obtém a propriedadefinida pelo parâmetro internalName de ListItem e os retorna do tipo genérico T. |
BaseSet(item ListItem, cadeia de caracteres internalName, valor do objeto) | Define a propriedade ListItem definida pelo parâmetro internalName. |
BaseSetTaxonomyField (item ListItem, cadeia de caracteres internalName, etiqueta de cadeia de caracteres, Guid termId) | Define o campo de taxonomia ListItem definido pelos parâmetros internalName e termId. |
BaseGetEnum (item ListItem, cadeia de caracteres internalName, T defaultValue) | Obtém o valor da propriedade enum definida pelo parâmetro internalName. Retorna o valor do parâmetro defaultValue se a propriedade não estiver configurada. |
O arquivo Event.cs contém as seguintes implementações dos métodos ReadProperties e SetProperties.
ReadProperties
protected override void ReadProperties(ListItem item) {
RegisteredEventId = BaseGet<string>(item, FIELD_REGISTERED_EVENT_ID);
Description = BaseGet<string>(item, FIELD_DESCRIPTION);
Category = BaseGet<string>(item, FIELD_CATEGORY);
EventDate = BaseGet<DateTime?>(item, FIELD_DATE);
Location = BaseGet<string>(item, FIELD_LOCATION);
ContactEmail = BaseGet<string>(item, FIELD_CONTACT_EMAIL);
Status = BaseGetEnum<EventStatus>(item, FIELD_STATUS);
var imageUrl = BaseGet<FieldUrlValue>(item, FIELD_IMAGE_URL);
if (imageUrl != null)
ImageUrl = imageUrl.Url;
}
SetProperties
protected override void SetProperties(ListItem item) {
BaseSet(item, FIELD_REGISTERED_EVENT_ID, RegisteredEventId);
BaseSet(item, FIELD_DESCRIPTION, Description);
BaseSet(item, FIELD_CATEGORY, Category);
BaseSet(item, FIELD_DATE, EventDate);
BaseSet(item, FIELD_LOCATION, Location);
BaseSet(item, FIELD_CONTACT_EMAIL, ContactEmail);
BaseSet(item, FIELD_STATUS, Status.ToEnumDescription());
BaseSet(item, FIELD_IMAGE_URL, ImageUrl);
}
Os exemplos de código a seguir mostram como os métodos BaseGet e BaseSet subjacentes estão definidos em BaseListItem.cs.
BaseGet
protected T BaseGet<T>(ListItem item, string internalName){
var field = _fields[internalName.ToLowerInvariant()];
var value = item[field.InternalName];
return (T)value;
}
BaseSet
protected void BaseSet(ListItem item, string internalName, object value) {
if (_fields.ContainsKey(internalName)) {
var field = _fields[internalName.ToLowerInvariant()];
if (field is FieldUrl && value is string) {
var urlValue = new FieldUrlValue() {
Url = value.ToString()
};
value = urlValue;
}
}
item[internalName] = value;
}
A classe BaseListItem também contém um método Salvar que é usado para salvar cada entidade linha de negócios (LOB) que o suplemento cria e manipula. Este método carrega a lista e determina se o item atual possui um ID maior que 0. Se o ID não for maior que 0, ele pressupõe que não é válido e cria um novo item de lista. Ele usa o método SetProperties para definir propriedades no ListItem e, em seguida, define as propriedades na subclasse usando o método ReadProperties.
public void Save(Web web) {
var context = web.Context;
var list = web.GetListByTitle(ListTitle);
if (!IsNew && Id > 0) {
ListItem = list.GetItemById(Id);
}
else {
var listItemCreationInfo = new ListItemCreationInformation();
ListItem = list.AddItem(listItemCreationInfo);
}
// Ensure that the fields have been loaded.
EnsureFieldsRetrieved(ListItem);
// Set the properties on the list item.
SetProperties(ListItem);
BaseSet(ListItem, TITLE, Title);
// Use if you want to override the created/modified date.
//BaseSet(ListItem, CREATED, Created);
//BaseSet(ListItem, MODIFIED, Modified);
ListItem.Update();
if (!string.IsNullOrEmpty(ContentTypeName)) {
var contentType = list.GetContentTypeByName(ContentTypeName);
if (contentType != null)
BaseSet(ListItem, "ContentTypeId", contentType.Id.StringValue);
}
ListItem.Update();
// Execute the batch.
context.ExecuteQuery();
// Reload the properties.
ListItem.RefreshLoad();
UpdateBaseProperties(ListItem);
ReadProperties(ListItem);
}