1
votes

I'm using DNN 9.3.2 and Chris Hammond's module template to create a custom module. When I load the module onto a page without visibility restrictions, it does not render. The Event Log does not contain any errors after installation or rendering of said page.

Since this is my first DNN MVC module, I'm thinking this has to do with the following controller class I've created:

    [DnnHandleError]
    public class SignupController : DnnController
    {
    // GET: Signup
    [ModuleAction(ControlKey = "Edit", TitleKey = "AddItem")]
    public ActionResult Index()
    {
        var signups = OnboardingManager.Instance.GetOnboardings(ModuleContext.ModuleId);
        return View(signups);
    }

    [HttpPost]
    [DotNetNuke.Web.Mvc.Framework.ActionFilters.ValidateAntiForgeryToken]
    public ActionResult Edit(Models.Onboarding onboarding)
    {
        ProPayService service = new ProPayService();

            OnboardingManager.Instance.CreateOnboarding(onboarding);
            service.MerchantSignupForProPayAsync();

            return RedirectToDefaultRoute();
    }

    public ActionResult Edit(int onboardingId = -1)
    {

     DotNetNuke.Framework.JavaScriptLibraries.JavaScript.RequestRegistration(CommonJs.DnnPlugins);

        var userlist = UserController.GetUsers(PortalSettings.PortalId);
        var users = from user in userlist.Cast<UserInfo>().ToList()
            select new SelectListItem { Text = user.DisplayName, Value = user.UserID.ToString() };

        ViewBag.Users = users;

        var onboarding = (onboardingId == -1) ? new Models.Onboarding{ModuleId = ModuleContext.ModuleId} : OnboardingManager.Instance.GetOnboarding(onboardingId, ModuleContext.ModuleId);
        return View(onboarding);

    }
}

The service class referenced above is defined as follows:

public class ProPayService
{
    private static HttpClient _httpClient = new HttpClient();
    //private readonly string _baseUrl = "https://xmltestapi.propay.com/ProPayAPI";
    Uri _baseUrl = new Uri("https://xmltestapi/propay.com/ProPayAPI");

    public ProPayResponse MerchantSignupForProPayAsync()
    {
        SignupRequest signupRequest = new SignupRequest();
            SignupResponse signupResponse = new SignupResponse();
            HttpContent content = new StringContent(signupRequest.ToString());
            CancellationToken cancellationToken = new CancellationToken();
            var credentials = GetCredentials();
            var responseBody = _httpClient.PutAsync(_baseUrl, content, cancellationToken).Result;
        try
        {
            BuildMerchantTestData();

            Console.WriteLine(responseBody);
            Console.WriteLine(content);
            if (WebRequest.Create(_baseUrl) is HttpWebRequest httpRequest)
            {
                httpRequest.Method = "PUT";
                httpRequest.Headers.Add("accept", "applicaiton/json");
                httpRequest.Headers.Add("Authorization", credentials);
            }

            //var httpRequest = new HttpRequestMessage(HttpMethod.Put, _baseUrl);
            //httpRequest.Headers.Add("Authorization", credentials);

            Console.WriteLine(signupResponse.Status);
        }
        catch (HttpRequestException e)
        {
            Console.WriteLine("\nException caught");
            Console.WriteLine("Message: {0} ", e.Message);
        }

        return JsonConvert.DeserializeObject<ProPayResponse>(responseBody.Content.ReadAsStringAsync().Result);
    }
    private SignupRequest BuildMerchantTestData()
    {
        int moduleId = 0;
        int OnboardingId = 0;
        var result = OnboardingManager.Instance.GetOnboarding(OnboardingId, moduleId);
        var onboardingList = new List<Models.Onboarding>();
        var ownerList = new List<OwnerList>();


        SignupRequest signupRequest = new SignupRequest();
        if (result != null)
        {
            Debug.Assert(result != null, nameof(OnboardingList) + " != null");
            Console.WriteLine("{0} {1}", result.Email, result.UserId);
            List<Owner> owner1 = new List<Owner>
            {
                new Owner
                {
                    FirstName = result.OwnerFirstName,
                    LastName = result.OwnerLastName,
                    Address = result.OwnerAddress,
                    City = result.OwnerCity,
                    State = result.OwnerRegion,
                    Zip = result.OwnerZipCode,
                    Country = result.OwnerCountry,
                    DateOfBirth = result.OwnerDob,
                    SSN = result.OwnerSsn,
                    Email = result.Email,
                    Percentage = result.OwnerPercentage,
                    Title = result.OwnerTitle
                }
            };
            signupRequest = new SignupRequest
            {
                PersonalData = new PersonalData
                {
                    FirstName = result.FirstName,
                    MiddleInitial = result.MiddleInitial,
                    LastName = result.Lastname,
                    DateOfBirth = result.DateOfBirth,
                    SocialSecurityNumber = result.Ssn,
                    SourceEmail = result.Email,
                    PhoneInformation =
                        new PhoneInformation
                        { DayPhone = result.DayPhone, EveningPhone = result.EveningPhone },

                },
                InternationalSignUpData = null,
                //InternationalSignUpData = new InternationalSignupData
                //{
                //    DocumentExpDateString = result.DocumentExpDate,
                //    DocumentIssuingState = result.DocumentIssuingState,
                //    DocumentType = result.DocumentType,
                //    DriversLicenseVersion = result.DriversLicenseVersion,
                //    InternationalId = result.InternationalId,
                //    MedicareCardColor = result.MedicareCardColor,
                //    MedicareReferenceNumber = result.MedicareReferenceNumber
                //},
                NotificationEmail = result.Email,
                SignupAccountData = new SignupAccountData
                {
                    CurrencyCode = "USD",
                    //UserId = result.UserId.ToString(),
                    //PhonePIN = result.PhonePin,
                    //ExternalId = "12345",
                    Tier = "Test"
                },
                BusinessData =
                    new BusinessData
                    {
                        BusinessLegalName = result.BusinessLegalName,
                        DoingBusinessAs = result.DoingBusinessAs,
                        EIN = result.Ein,
                        MerchantCategoryCode = result.MerchantCategoryCode,
                        WebsiteURL = result.BusinessUrl,
                        BusinessDescription = result.BusinessDescription,
                        MonthlyBankCardVolume = result.MonthlyBankCardVolume ?? 0,
                        AverageTicket = result.AverageTicket ?? 0,
                        HighestTicket = result.HighestTicket ?? 0
                    },
                Address = new Address
                {
                    ApartmentNumber = result.Address1ApartmentNumber,
                    Address1 = result.Address1Line1,
                    Address2 = result.Address1Line1,
                    City = result.Address1City,
                    State = result.Address1State,
                    Country = result.Address1Country,
                    Zip = result.Address1ZipCode
                },
                MailAddress = new Address
                {
                    ApartmentNumber = result.OwnerApartmentNumber,
                    Address1 = result.OwnerAddress,
                    Address2 = result.OwnerAddress2,
                    City = result.OwnerCity,
                    State = result.OwnerRegion,
                    Country = result.OwnerCountry,
                    Zip = result.OwnerZipCode
                },
                BusinessAddress =
                    new Address
                    {
                        ApartmentNumber = result.BusinessApartmentNumber,
                        Address1 = result.BusinessAddressLine1,
                        Address2 = result.BusinessAddressLine2,
                        City = result.BusinessCity,
                        State = result.BusinessState,
                        Country = result.BusinessCountry,
                        Zip = result.BusinessZipCode
                    },
                //CreditCardData = new CreditCardData
                //{
                //    NameOnCard = result.NameOnCard,
                //    CreditCardNumber = result.CreditCardNumber, // test card number
                //    ExpirationDate = result.ExpirationDate
                //},


                BankAccount =
                    new BankAccount
                    {
                        AccountCountryCode = result.BankAccount1CountryCode,
                        BankAccountNumber = result.BankAccount1Number,
                        RoutingNumber = result.BankAccount1RoutingNumber,
                        AccountOwnershipType = result.BankAccount1OwnershipType,
                        BankName = result.BankAccount1BankName,
                        AccountType = "Checking",
                        //AccountType = result.BankAccount1Type,
                        AccountName = result.BankAccount1Name,
                        Description = result.BankAccount1Description
                    },
                //SecondaryBankAccount =
                //    new BankAccount
                //    {
                //        AccountCountryCode = result.BankAccount2CountryCode,
                //        BankAccountNumber = result.BankAccount2Number,
                //        RoutingNumber = result.BankAccount2RoutingNumber,
                //        AccountOwnershipType = result.BankAccount2OwnershipType,
                //        BankName = result.BankAccount2BankName,
                //        AccountType = result.BankAccount2Type,
                //        AccountName = result.BankAccount2Name,
                //        Description = result.BankAccount2Description
                //    },
                //GrossBillingInformation = new GrossBillingInformation
                //{
                //    GrossSettleAddress = new Address
                //    {
                //        Address1 = result.OwnerAddress,
                //        Address2 = result.OwnerAddress2,
                //        ApartmentNumber = result.OwnerApartmentNumber,
                //        City = result.OwnerCity,
                //        Country = result.OwnerCountry,
                //        State = result.OwnerRegion,
                //        Zip = result.OwnerZipCode
                //    },
                //    GrossSettleBankAccount = new BankAccount
                //    {
                //        AccountCountryCode = "USA",
                //        AccountName = result.BankAccount1Name,
                //        AccountOwnershipType = result.BankAccount1OwnershipType,
                //        AccountType = result.BankAccount1Type,
                //        BankAccountNumber = result.BankAccount1Number,
                //        BankName = result.BankAccount1BankName,
                //        Description = result.BankAccount1Description,
                //        RoutingNumber = result.BankAccount1RoutingNumber
                //    },
                //    GrossSettleCardData = new CreditCardData
                //    {
                //        CreditCardNumber = result.CreditCardNumber,
                //        ExpirationDate = result.ExpirationDate,
                //        NameOnCard = result.NameOnCard
                //    }
                //},
                //FraudDetectionData = new FraudDetectionData
                //{
                //    MerchantSourceIp = result.MerchantSourceIp,
                //    ThreatMetrixPolicy = result.ThreatMetrixPolicy,
                //    ThreatMetrixSessionId = result.SessionId
                //},
                //PaymentMethodId = result.PaymentMethodId,
                //PaymentBank = new BankAccount
                //{
                //    AccountName = result.PaymentBankAccountName,
                //    AccountCountryCode = result.PaymentBankCountryCode,
                //    AccountOwnershipType = result.PaymentBankOwnershipType,
                //    AccountType = result.PaymentBankAccountType,
                //    BankAccountNumber = result.PaymentBankAccountNumber,
                //    BankName = result.PaymentBankName,
                //    Description = result.PaymentBankAccountDescription,
                //    RoutingNumber = result.PaymentBankRoutingNumber
                //}
                BeneficialOwnerData = new BeneficialOwnerData
                {
                    OwnerCount = "1",
                    Owners = owner1
                }
            };

            Console.WriteLine(JsonConvert.SerializeObject(signupRequest));
        }

        //return new SignUpRequest();
        return signupRequest;
    }


    private static string GetCredentials()
    {
        var termId = "myId"; // put affiliate term id here, if you have it
        var certString = "myCert"; // put affiliate cert string here
        var encodedCredentials = Convert.ToBase64String(Encoding.Default.GetBytes(certString + ":" + termId));

        var credentials = $"Basic {encodedCredentials}";
        return credentials;
    }
}

The DNN manifest file is defined as follows:

<dotnetnuke type="Package" version="5.0">
<packages>
<package name="Onboarding" type="Module" version="00.00.01">
  <friendlyName>Onboarding</friendlyName>
  <description>Onboarding</description>
  <iconFile>~/Icons/Sigma/Software_32X32_Standard.png</iconFile>
  <owner>
    <name>SocialBodega.com</name>
    <organization>SocialBodega.com</organization>
    <url>https://www.socialbodega.com/</url>
    <email>[email protected]</email>
  </owner>
  <license src="License.txt"></license>
  <releaseNotes src="ReleaseNotes.txt"></releaseNotes>
  <dependencies>
    <dependency type="CoreVersion">08.00.00</dependency>
  </dependencies>
  <components>
    <component type="Script">
      <scripts>
        <basePath>DesktopModules\MVC\Onboarding</basePath>
        <script type="Install">
          <path>Providers\DataProviders\SqlDataProvider</path>
          <name>00.00.01.SqlDataProvider</name>
          <version>00.00.01</version>
        </script>
        <script type="UnInstall">
          <path>Providers\DataProviders\SqlDataProvider</path>
          <name>Uninstall.SqlDataProvider</name>
          <version>00.00.01</version>
        </script>
      </scripts>
    </component>
    <component type="ResourceFile">
      <resourceFiles>
        <basePath>DesktopModules/MVC/Onboarding</basePath>
        <resourceFile>
          <name>Resources.zip</name>
        </resourceFile>
      </resourceFiles>
    </component>
    <component type="Module">
      <desktopModule>
        <moduleName>Onboarding</moduleName>
        <foldername>Onboarding</foldername>
        <businessControllerClass>SocialBodega.Onboarding.Components.FeatureController</businessControllerClass>
        <supportedFeatures />
        <moduleDefinitions>
          <moduleDefinition>
            <friendlyName>Onboarding</friendlyName>
            <defaultCacheTime>0</defaultCacheTime>
            <moduleControls>
              <!--<moduleControl>
                <controlKey />
                <controlSrc>SocialBodega.Onboarding.Controllers/Item/Index.mvc</controlSrc>
                <supportsPartialRendering>False</supportsPartialRendering>
                <controlTitle />
                <controlType>View</controlType>
                <iconFile />
                <helpUrl />
                <viewOrder>0</viewOrder>
              </moduleControl>-->
              <moduleControl>
                <controlKey/>
                <controlSrc>SocialBodega.Onboarding.Controllers/Signup/Index.mvc</controlSrc>
                <supportPartialRendering>False</supportPartialRendering>
                <controlTitle/>
                <controlType>View</controlType>
                <iconFile/>
                <helpUrl/>
                <viewOrder>0</viewOrder>
                <supportsPopUps>True</supportsPopUps>
              </moduleControl>
              <moduleControl>
                <controlKey>Edit</controlKey>
                <controlSrc>SocialBodega.Onboarding.Controllers/Signup/Edit.mvc</controlSrc>
                <supportsPartialRendering>False</supportsPartialRendering>
                <controlTitle>Edit Signups</controlTitle>
                <controlType>Edit</controlType>
                <iconFile />
                <helpUrl />
                <viewOrder>0</viewOrder>
                <supportsPopUps>True</supportsPopUps>
              </moduleControl>
              <moduleControl>
                <controlKey>Settings</controlKey>
                <controlSrc>SocialBodega.Onboarding.Controllers/Settings/Settings.mvc</controlSrc>
                <supportsPartialRendering>False</supportsPartialRendering>
                <controlTitle>Onboarding Settings</controlTitle>
                <controlType>Edit</controlType>
                <iconFile />
                <helpUrl />
                <viewOrder>0</viewOrder>
              </moduleControl>
            </moduleControls>
          </moduleDefinition>
        </moduleDefinitions>
      </desktopModule>
    </component>
    <component type="Assembly">
      <assemblies>
        <assembly>
          <name>Onboarding.dll</name>
          <path>bin</path>
        </assembly>
      </assemblies>
    </component>
  </components>
</package>
</packages>
</dotnetnuke>

Are there changes I should make to my above controller to ensure that the module renders properly? Or are there other items I should review to further diagnose the issue?

Update: After making a change to the DNN manifest as per comment, I am now unable to add the module to the page and receive the following in admin log:

AbsoluteURL:

DefaultDataProvider:DotNetNuke.Data.SqlDataProvider, DotNetNuke

ExceptionGUID:e229902b-051f-459e-9647-28adcd0d4f50

AssemblyVersion:

PortalId:-1

UserId:-1

TabId:-1

RawUrl:

Referrer:

UserAgent:

ExceptionHash:OLQuqVQLbGm0IndDqnMOfMf2C3Q=

Message:Error Creating BusinessControllerClass 
'SocialBodega.Onboarding.Components.FeatureController, SocialBodega.Onboarding' of module(Onboarding) id=(422) in tab(41) and portal(0)

StackTrace:

at DotNetNuke.Services.Search.ModuleIndexer.ThrowLogError(ModuleInfo module, 
Exception ex)
InnerMessage:Value cannot be null. Parameter name: type

InnerStackTrace:

at System.Activator.CreateInstance(Type type, Boolean nonPublic) at 
System.Activator.CreateInstance(Type type) at 
DotNetNuke.Services.Search.ModuleIndexer.GetModuleList(Int32 portalId)
Source:DotNetNuke

My revised DNN Manifest is listed below:

<dotnetnuke type="Package" version="5.0">
<packages>
<package name="Onboarding" type="Module" version="00.00.01">
  <friendlyName>Onboarding</friendlyName>
  <description>Onboarding</description>
  <iconFile>~/Icons/Sigma/Software_32X32_Standard.png</iconFile>
  <owner>
    <name>SocialBodega.com</name>
    <organization>SocialBodega.com</organization>
    <url>https://www.socialbodega.com/</url>
    <email>[email protected]</email>
  </owner>
  <license src="License.txt"></license>
  <releaseNotes src="ReleaseNotes.txt"></releaseNotes>
  <dependencies>
    <dependency type="CoreVersion">08.00.00</dependency>
  </dependencies>
  <components>
    <component type="Script">
      <scripts>
        <basePath>DesktopModules\MVC\Onboarding</basePath>
        <script type="Install">
          <path>Providers\DataProviders\SqlDataProvider</path>
          <name>00.00.01.SqlDataProvider</name>
          <version>00.00.01</version>
        </script>
        <script type="UnInstall">
          <path>Providers\DataProviders\SqlDataProvider</path>
          <name>Uninstall.SqlDataProvider</name>
          <version>00.00.01</version>
        </script>
      </scripts>
    </component>
    <component type="ResourceFile">
      <resourceFiles>
        <basePath>DesktopModules/MVC/Onboarding</basePath>
        <resourceFile>
          <name>Resources.zip</name>
        </resourceFile>
      </resourceFiles>
    </component>
    <component type="Module">
      <desktopModule>
        <moduleName>Onboarding</moduleName>
        <foldername>Onboarding</foldername>
     <businessControllerClass>SocialBodega.Onboarding.
     Components.FeatureController, 
     SocialBodega.Onboarding</businessControllerClass>
        <supportedFeatures />
        <moduleDefinitions>
          <moduleDefinition>
            <friendlyName>Onboarding</friendlyName>
            <defaultCacheTime>0</defaultCacheTime>
            <moduleControls>
              <!--<moduleControl>
                <controlKey />
             <controlSrc>SocialBodega.Onboarding.Controllers/Item/Index.mvc
             </controlSrc>
                <supportsPartialRendering>False</supportsPartialRendering>
                <controlTitle />
                <controlType>View</controlType>
                <iconFile />
                <helpUrl />
                <viewOrder>0</viewOrder>
              </moduleControl>-->
              <moduleControl>
                <controlKey/>

          <controlSrc>SocialBodega.Onboarding.Controllers/Signup/Index.mvc
          </controlSrc>
                <supportPartialRendering>False</supportPartialRendering>
                <controlTitle/>
                <controlType>View</controlType>
                <iconFile/>
                <helpUrl/>
                <viewOrder>0</viewOrder>
                <supportsPopUps>True</supportsPopUps>
              </moduleControl>
              <moduleControl>
                <controlKey>Edit</controlKey>


           <controlSrc>SocialBodega.Onboarding.Controllers/Signup/Edit.mvc
           </controlSrc>
                <supportsPartialRendering>False</supportsPartialRendering>
                <controlTitle>Edit Signups</controlTitle>
                <controlType>Edit</controlType>
                <iconFile />
                <helpUrl />
                <viewOrder>0</viewOrder>
                <supportsPopUps>True</supportsPopUps>
              </moduleControl>
              <moduleControl>
                <controlKey>Settings</controlKey>

       <controlSrc>SocialBodega.Onboarding.Controllers/Settings/Settings.mvc
       </controlSrc>
                <supportsPartialRendering>False</supportsPartialRendering>
                <controlTitle>Onboarding Settings</controlTitle>
                <controlType>Edit</controlType>
                <iconFile />
                <helpUrl />
                <viewOrder>0</viewOrder>
              </moduleControl>
            </moduleControls>
          </moduleDefinition>
        </moduleDefinitions>
      </desktopModule>
    </component>
    <component type="Assembly">
      <assemblies>
        <assembly>
          <name>Onboarding.dll</name>
          <path>bin</path>
        </assembly>
      </assemblies>
    </component>
  </components>
</package>

Update2 I upgraded to DNN 9.4 late last week and took the advice received to comment out all code in my view and just render a label. This worked!! Thus, my view syntax is as per below:

@inherits 
DotNetNuke.Web.Mvc.Framework.DnnWebViewPage
<DotNetNuke.Collections.PagedList<SocialBodega.Onboarding.
Models.Onboarding>>

@using System.Linq
@using System.Text.RegularExpressions
@using DotNetNuke.Collections
@using DotNetNuke.Entities.Urls
@using DotNetNuke.Web.Mvc.Helpers

<div id="[email protected]">
@if (Model == null|| !Model.Any())

    {
    <p>@Dnn.LocalizeString("NoSignups")</p>
}
else
{
    <ul>
        @foreach (var onboarding in Model)
        {
            <li>
                <h3>@onboarding.FirstName</h3>
                <div>@onboarding.OnboardingId</div>
                @{
                    if (Dnn.ModuleContext.IsEditable)
                    {
                        <div>
                            <a href="@Url.Action("Edit","Signup", new{ctl = "Edit", onboardingId = onboarding.OnboardingId, })">@Dnn.LocalizeString("EditItem")</a>
                        </div>
                    }
                }
            </li>
        }
    </ul>
}
</div>
@*@Html.Label("Testing 123");*@

When I build the solution, it succeeds but I do receive 16 error messages in Visual Studio 2019 to the effect of:

Error   CS0012  The type 'WebViewPage<>' is defined in an assembly that is 
not referenced. You must add a reference to assembly 'System.Web.Mvc, 
Version=5.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.  
1_desktopmodules_mvc_onboarding_Views_Signup_Index.cshtml    
C:\websites\dnndev.me\DesktopModules\Onboarding\Views\Signup\Index.cshtml   

I've added said assembly to web.config in the Views folder of the module and also to the main DNN web.config at C:\websites.dnndev.me using the following:

    <compilation debug="true" targetFramework="4.7.2">
  <assemblies>
    <add assembly="System.Web.Mvc, Version = 5.1.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35"/>
    <add assembly ="netstandard, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = cc7b13ffcd2ddd51"/>
  </assemblies>
</compilation>

How do I prevent the errors from being thrown and ensure that my view renders as desired?

1
I would use a sniffer like wireshark or fiddler and see if you are getting a status of 200 OK. You may be getting an error. returning an empty response, or getting no response. If you have an app that does work compare first request in working code with non working code. Then make you c# look like working code. - jdweng
So Fiddler gives HTTP 200 when I browse the page that has the nodule installed. - SidC
Then the HttpPost and request are good and the issue is with parsing the response. The code posted is for the request not the response. - jdweng
Can you post your dnn manifest too? - Fix It Scotty
I've added my service class logic and the contents of DNN manifest in the updated question. Appreciate your help. - SidC

1 Answers

1
votes

First, be sure your module is compiling against the correct version of .NET Framework that your DNN instance is targeting. You can look for a line in your web.config file, similar to this one:

<compilation debug="false" strict="false" targetFramework="4.5">  

In recent versions of DNN, you'll need to be sure to explicitly tell DNN that permissions that your controller is meant to be responding to. Take note of the DnnModuleAuthorize class decoration in the sample below.

using System;  
using System.Web.Mvc;  
using DotNetNuke.Entities.Modules;  
using DotNetNuke.Security;  
using DotNetNuke.Services.Exceptions;  
using DotNetNuke.Web.Mvc.Framework.ActionFilters;  

namespace SocialBodega.Onboarding.Controllers   
{   
    [DnnModuleAuthorize(AccessLevel = SecurityAccessLevel.View)]  
    [DnnHandleError]  
    public class SignupController : DnnBaseController  
    {  
        // GET: Signup  
        [ModuleAction(ControlKey = "Edit", TitleKey = "AddItem")]  
        public ActionResult Index()  
        {  
            var signups = OnboardingManager.Instance.GetOnboardings(ModuleContext.ModuleId);  
            return View(signups);  
        }  
    }  
}