Pdf Document Link control error - PdfDocumentLink.ascx - sitefinity

I just upgraded from 5.1 to 7.0 and now I am getting this error on one of the pages that have a PdfDocumentLink control (in Edit Mode):
A required control was not found in the template for "~/Sitefinity/Extensions/WidgetTemplates/Libraries/Documents/PdfDocumentLink.ascx". The control must be assignable from type "System.Web.UI.HtmlControls.HtmlGenericControl" and must have ID "itemsContainer".
I get a 500 in Preview mode.
This is the code for the ascx, in \Sitefinity\Extensions\WidgetTemplates\Libraries\Documents
<%# Control Language="C#" %>
<%# Register TagPrefix="sitefinity" Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI" %>
<%# Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.PublicControls.BrowseAndEdit" Assembly="Telerik.Sitefinity" %>
<sitefinity:ResourceLinks id="resourcesLinks2" runat="server" UseEmbeddedThemes="false" Theme="Default">
<sitefinity:ResourceFile Name="~/Sitefinity/Extensions/WidgetTemplates/Libraries/Documents/PdfDocumentLink.css" Static="true" />
</sitefinity:ResourceLinks>
<sitefinity:SitefinityHyperLink ID="documentLink" runat="server" target="_blank" CssClass="PdfDocumentLink" />
<sf:BrowseAndEditToolbar ID="browseAndEditToolbar" runat="server" Mode="Edit"></sf:BrowseAndEditToolbar>
Here's the cs file ... under C:\inetpub\xxx\App_Code\Widgets
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace xxx.Sitefinity.Widgets.Libraries.Documents {
/// <summary>
/// Summary description for PdfDocumentLink
/// </summary>
public class PdfDocumentLink : Telerik.Sitefinity.Modules.Libraries.Web.UI.Documents.DocumentLink {
public PdfDocumentLink() : base () {
//
// TODO: Add constructor logic here
//
}
public override string LayoutTemplatePath {
get {
return "~/Sitefinity/Extensions/WidgetTemplates/Libraries/Documents/PdfDocumentLink.ascx";
}
set {
base.LayoutTemplatePath = value;
}
}
public string LinkTitle {
get;
set;
}
protected override void OnPreRender(EventArgs e) {
base.OnPreRender(e);
if (this.LinkTitle != null)
this.DocumentLinkControl.Text = this.LinkTitle;
}
}
}
And ToolboxesConfig.config file:
...
<toolboxesConfig xmlns:config="urn:telerik:sitefinity:configuration" xmlns:type="urn:telerik:sitefinity:configuration:type" config:version="7.0.5100.0">
<toolboxes>
<toolbox name="PageControls">
<sections>
<add name="ContentToolboxSection">
<tools>...
<add enabled="True" type="OneCommand.Sitefinity.Widgets.Libraries.Documents.PdfDocumentLink" title="PDF Document Link" description="Link to a PDF Document" cssClass="sfDownloadLinkIcn" moduleName="Libraries" Name="PDFDocumentLink" visibilityMode="None" name="PDFDocumentLink" />
If I delete the widget, and add it back in, and select a pdf document, I get the same error.
The Document Link widget appears to work ok, but that one doesn't have the left side PDF icon that we want to display.
Any ideas?

Try adding this to your .ascx file:
<div runat="server" id="itemsContainer"></div>

Related

Getting values from SQL table in Evoq (DotNetNuke), DNN custom Module

I am not so familiar with c# or asp.net. If you have a solution, please keep this in mind when explaining.
I am using DNN and Evoq. I have created a new module using Module Creator. I need to access my table (Test_Table). This table is internal it's part of DNN/Evoq database.
I can access it when i go to Evoq (CMS), settings, SQL Console. (Example: Select * from Test_Table) The table is set up correctly.
These are the starter files I got when i created the module:
View.ascx, View.ascx.cs and In App_LocalResources View.ascx
My Question.
How do i get the table values for Test_Table, a table that is not external but part of DNN/Evoq database. There is also no security / login requirements for this table.
Code on: View.ascx.cs
#region Using Statements
using System;
using DotNetNuke.Entities.Modules;
#endregion
namespace TestFormSupport1.MyTestFormSupport1
{
public partial class View : PortalModuleBase
{
#region Event Handlers
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
cmdSave.Click += cmdSave_Click;
cmdCancel.Click += cmdCancel_Click;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!Page.IsPostBack)
{
txtField.Text = (string)Settings["field"];
}
}
protected void cmdSave_Click(object sender, EventArgs e)
{
ModuleController.Instance.UpdateModuleSetting(ModuleId, "field", txtField.Text);
DotNetNuke.UI.Skins.Skin.AddModuleMessage(this, "Update Successful 3", DotNetNuke.UI.Skins.Controls.ModuleMessage.ModuleMessageType.GreenSuccess);
}
protected void cmdCancel_Click(object sender, EventArgs e)
{
}
#endregion
}
}
Code on View.ascx
<%# Control Language="C#" AutoEventWireup="false" Inherits="TestFormSupport1.MyTestFormSupport1.View" CodeFile="View.ascx.cs" %>
<%# Register TagPrefix="dnn" TagName="Label" Src="~/controls/LabelControl.ascx" %>
<div class="dnnForm dnnEdit dnnClear" id="dnnEdit">
<fieldset>
<div class="dnnFormItem">
<dnn:label id="plField" runat="server" text="Field" helptext="Enter a value" controlname="txtField" />
<asp:textbox id="txtField" runat="server" maxlength="255" />
</div>
</fieldset>
<ul class="dnnActions dnnClear">
<li><asp:linkbutton id="cmdSave" text="Save" runat="server" cssclass="dnnPrimaryAction" /></li>
<li><asp:linkbutton id="cmdCancel" text="Cancel" runat="server" cssclass="dnnSecondaryAction" /></li>
</ul>
</div>
Thanks in advance
DNN has different possibilities to access data - DAL, DAL+ and DAL2 (which is the "newest" one). To find an example read Using DAL 2 in a real world module.

Updating a property in a viewmodel of popup doesn't update the UI

As in the title I have a problem where updating a property in a viewmodel of popup doesn't update the UI. I use popups from xamarin community toolkit. I'm using a command that does this task:
async Task ShowPopup()
{
MessagingCenter.Send(AnimeGroupObservable, "AnimeGroups");
Shell.Current.ShowPopup(new MediaListGroupsPopup());
}
It sends a message with payload and shows popup. This is popup viewmodel:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows.Input;
using OtakuApp.Models;
using Xamarin.Forms;
namespace OtakuApp.ViewModels
{
class MediaListGroupsPopupViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string name = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public ObservableCollection<Group> _AnimeGroups = new ObservableCollection<Group>();
public ObservableCollection<Group> AnimeGroups
{
get => _AnimeGroups;
set
{
if (_AnimeGroups == value)
return;
_AnimeGroups = value;
OnPropertyChanged();
}
}
public String _label;
public String label
{
get => _label;
set
{
if (value == _label)
return;
_label = value;
OnPropertyChanged();
}
}
public MediaListGroupsPopupViewModel()
{
MessagingCenter.Subscribe<ObservableCollection<Group>>(this, "AnimeGroups", (AnimeGroupObservable) =>
{
Console.WriteLine(AnimeGroupObservable[0].Name);
label = AnimeGroupObservable[1].Name;
MessagingCenter.Unsubscribe<ObservableCollection<Group>>(this, "AnimeGroups");
});
}
}
}
I'm planning on having a small collection view of labels to select from. But right now I'm struggling to update one label just for testing purposes, so you can imagine that I've tried collection view and it didn't work. Setting _label to something manually in the code shows that binding works. It's just not updating for some reason.
Popup xaml file:
<?xml version="1.0" encoding="utf-8" ?>
<xct:Popup
x:Class="OtakuApp.Popups.MediaListGroupsPopup"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
Size="300,300">
<StackLayout>
<Label Text="{Binding label}" />
</StackLayout>
</xct:Popup>
So right now I have two problems:
Label doesn't update. It's binded to a property that has INotifyPropertyChanged
Weirdly this subscription happens only the second time (and after that too, just not the first time) I open up a popup. Is this because it's in the constructor? If yes, what's the correct way to deal with it?
Also a small question - I have unsubscribe at the end of subscription. When I didn't have it and I printed out AnimeGroupObservable[0].Name, the first time it was printed one time, the second time I open up the popup two times etc. Is the unsubscribe at the end the correct way to fix this?
since you are passing a single parameter to a single page, using the constructor would be much simpler than MessagingCenter (which is great, but overkill for this scenario)
when creating the page, pass the parameter in the constructor
Shell.Current.ShowPopup(new MediaListGroupsPopup(AnimeGroupObservable));
then modify the page constructor to accept the parameter
public MediaListGroupsPopup(ObservableCollection<Group> groups)
{
// you did't show how you create your VM, but I assume it's something like this
this.BindingContext = new MediaListGroupsPopupViewModel(groups);
}
then modify your VM constructor
public MediaListGroupsPopupViewModel(ObservableCollection<Group> groups)
{
label = groups[1].Name;
}
if you really are only using a single string value, you could just pass that instead of the entire ObservableCollection

How to name properties of child objects while using ValidationMessage

I'm using two kinds of validation: Client Side and Server Side on a Blazor Project.
Client side is using DataAnnotations, as usual and DataAnnotationsValidator and is working just fine.
Server Side is using this custom server side validation component:
public sealed class ServerSideValidator : ComponentBase
{
private ValidationMessageStore _messageStore;
[CascadingParameter]
private EditContext CurrentEditContext { get; set; }
protected override void OnInitialized()
{
if (CurrentEditContext == null)
{
throw new InvalidOperationException($"{nameof(ServerSideValidator)} requires a cascading " +
$"parameter of type {nameof(EditContext)}. For example, you can use {nameof(ServerSideValidator)} " +
$"inside an {nameof(EditForm)}.");
}
_messageStore = new ValidationMessageStore(CurrentEditContext);
CurrentEditContext.OnValidationRequested += (s, e) => _messageStore.Clear();
CurrentEditContext.OnFieldChanged += (s, e) => _messageStore.Clear(e.FieldIdentifier);
}
public void DisplayErrors(Dictionary<string, List<string>> errors)
{
foreach (var (elementId, errorsForElement) in errors)
{
_messageStore.Add(CurrentEditContext.Field(elementId), errorsForElement);
}
CurrentEditContext.NotifyValidationStateChanged();
}
}
And it's also working fine for "direct" properties of the model.
<ValidationMessage For="#(() => model.Property)"/>
Works great. Textbox is red rounded if it's invalid, after the server validation.
Problem is that properties of child model object are being validated (model is set as invalid) and are displayed on ValidationSummary, but the invalid field is not being marked as that.
<ValidationMessage For="#(() => model.Child.Property )"/>
So this is partially working.
When I'm server side validating the attribute, I'm populating the expected list:
IDictionary<string, List<string>> validationErrors
For direct childs (which works) I'm doing:
validationErrors.Add("fieldName", new List {"Is invalid...."});
For childs of model (which doesn't work) I'm doing:
validationErrors.Add("childName.fieldName", new List {"Is invalid...."});
As you can see, although child property is invalid, and form is invalid, jquery shows it as valid.
How do I need to name that property in order for the validator to display the errors?
You need to use the ObjectGraphDataAnnotationsValidator (if you want to use a custom implementation you can find the sources online).
It's in preview but it works fine.
Add this reference to your project:
<PackageReference Include="Microsoft.AspNetCore.Components.DataAnnotations.Validation" Version="3.2.0-rc1.20223.4" />
and use it instead of DataAnnotationsValidator:
<EditForm EditContext="#editContext" OnSubmit="#OnSubmit">
#* replace this => <DataAnnotationsValidator /> *#
<ObjectGraphDataAnnotationsValidator />
<ValidationSummary />
...

ASP.NET Core 2.0 and TagHelper Example

I am trying to following the following tutorial using ASP.NET Core 2.0. The code is supposed to replace the <email> tag with an anchor tag <a href="mailto:email#something.com" />. When I run the project the TagHelper code is never executed. Any suggestions would be greatly appreciated.
NOTE: It appears to be an issue with the visual studio project. I was able to find a visual studio code sample that worked with TagHelpers and recreate my project using it as a template and it worked. I did a comparison of my project and the working project but I didn't find any major differences in the .sln or .csproj files to explain the problem.
Here is the TagHelper class:
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Threading.Tasks;
namespace AuthoringTagHelpers.TagHelpers
{
[HtmlTargetElement("email")]
public class EmailTagHelper : TagHelper
{
private const string EmailDomain = "contoso.com";
// Can be passed via <email mail-to="..." />.
// Pascal case gets translated into lower-kebab-case.
[HtmlAttributeName("mail-to")]
public string MailTo { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "a"; // Replaces <email> with <a> tag
var address = MailTo + "#" + EmailDomain;
output.Attributes.SetAttribute("href", "mailto:" + address);
output.Content.SetContent(address);
}
}
}
Here is the view that is using the TagHelper:
#{
ViewData["Title"] = "About";
}
<h2>#ViewData["Title"]</h2>
<h3>#ViewData["Message"]</h3>
<p>Use this area to provide additional information.</p>
<address>
<strong>Support:</strong><email mail-to="Support"></email><br />
<strong>Marketing:</strong><email mail-to="Marketing"></email>
</address>
I added the following to _ViewImports.cshtml:
#addTagHelper *, AuthoringTagHelpers
To make the EmailTagHelper class available to all our Razor views, add the addTagHelper directive to the Views/_ViewImports.cshtml file:
#using AuthoringTagHelpers
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#addTagHelper *, AuthoringTagHelpers
You need to add the above code in _viewimports file. Right now you're added it in View.

Do need to databind in gridview?

If dt_grid.Rows.Count > 0 Then
dt_grid.DataSource = dt_grid
Else
MessageBox.Show("Not Found Data")
End If
I know that if get datatable in gridview.datasource,ever write gridview.Databind.But I found coding of my friend. He write only get datatable in gridview.datasource but no write gridview.dataBind. Therefore, his coding is not error. Why? Don't need to dataBind?
Are you sure your friend is not using the DataSourceID property?
Here is the difference from MSDN:
When the DataSourceID property is set (instead of the DataSource property), the data-bound control automatically binds to the data source control at run time.
Please take a look at this article and this one.
Hope it helped.
I took the time to do a small example to demonstrate that you need to call DataBind() on a normal asp.net gridview in order to render its data.
If your friend is not calling this, I am guessing that he is binding the grid to a data source in the .aspx code (to a SQLDatasource, on even an ObjectDataSource) and he is modifying that datasource in the code.
Please take a look at the following example:
The default.aspx page:
<%# Page Title="Home Page" Language="C#" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="GridViewDemo._Default" %>
<form id="form1" runat="server">
<asp:gridview id="GridView1" runat="server">
<Columns>
<asp:BoundField DataField="ID" />
<asp:BoundField DataField="Name" />
</Columns>
</asp:gridview>
</form>
The codebehind for the page: (it is in C# but I think it is relevant to VB as well)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace GridViewDemo
{
public partial class _Default : System.Web.UI.Page
{
public class Entity
{
public int ID { get; set; }
public string Name { get; set; }
}
protected void Page_Load(object sender, EventArgs e)
{
List<Entity> source = new List<Entity>() { new Entity() { ID = 1, Name = "First" }, new Entity() { ID = 2, Name = "Second" } };
GridView1.DataSource = source;
GridView1.DataBind();
// if you comment this line and run, the gridview is not rendered
}
}
}
Let me know if this answered your question.