web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

Community site session details

Community site session details

Session Id :
Customer experience | Sales, Customer Insights,...
Answered

Form Submission Fails, Custom Validation Plugin (D365 Real Time Marketing Form)

(4) ShareShare
ReportReport
Posted on by 18

Hi everyone,

I'm working on a Dynamics 365 Marketing form where I use a custom plugin for server-side validation. The plugin runs correctly and does not throw exceptions. It deserializes the msdynmkt_formsubmissionrequest, checks a custom field (nnc_event_registration_id) against a custom entity, and sets a response based on whether the code is valid.

In the plugin, I build the response like this:

 
var resp = new ValidateFormSubmissionResponse()
{
IsValid = isValid,
ValidationOnlyFields = new List<string> { "nnc_event_registration_id" },
ValidationErrorMessage = string.IsNullOrEmpty(errorMessage) ? null : errorMessage
};
context.OutputParameters["msdynmkt_validationresponse"] = Serialize(resp);
 
 

The issue:

Even when IsValid = true is returned, the form submission still fails with a general "there was an error with the submission" message.
There are no plugin exceptions, no meaningful errors in the logs — just the form failure. 


 

What I am trying to achieve:

  • If the code (nnc_event_registration_id) is invalid, display a friendly validation error message (e.g., "Please enter the Invite Code.") to the user.

  • If the code is valid, allow the form to submit normally without blocking anything.


 

Where I am stuck:

  • Do I even need to set ValidationOnlyFields if I just want to block or allow the full form submission based on a simple yes/no validation?

  • Could ValidationOnlyFields cause the form to behave differently, e.g., preventing full submission even if IsValid = true?

  • The documentation around how msdynmkt_validationresponse, ValidationOnlyFields, and IsValid interact during full form submission is very unclear.


 

Extra info:


 

Any help would be much appreciated — especially any clarification on whether ValidationOnlyFields must be set or not when trying to block or continue full form submission in Dynamics 365 Marketing.

 

Here is the full code:

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.IO;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
 
namespace DynamicsPlugins
{
public class nnc_event_registration_code_validierung : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var service = serviceFactory.CreateOrganizationService(context.UserId);
 
tracingService.Trace("Starting plugin execution.");
 
try
{
tracingService.Trace("Checking input parameters.");
if (!context.InputParameters.Contains("msdynmkt_formsubmissionrequest") || context.InputParameters["msdynmkt_formsubmissionrequest"] == null)
{
tracingService.Trace("Form submission request is missing.");
throw new InvalidPluginExecutionException("Form submission data not found.");
}
 
var requestString = (string)context.InputParameters["msdynmkt_formsubmissionrequest"];
 
if (string.IsNullOrWhiteSpace(requestString))
{
tracingService.Trace("Form submission request string is empty.");
throw new InvalidPluginExecutionException("Empty form submission data.");
}
 
tracingService.Trace($"Form submission request string: {requestString}");
 
tracingService.Trace("Deserializing form submission request.");
var requestObject = Deserialize<FormSubmissionRequest>(requestString);
 
if (requestObject == null)
{
tracingService.Trace("Deserialized form submission object is null.");
throw new InvalidPluginExecutionException("Invalid form submission data.");
}
 
if (requestObject.Fields == null || !requestObject.Fields.Any())
{
tracingService.Trace("Fields list is missing or empty.");
SetValidationResponse(context, false, "Bitte geben Sie einen Einladungscode ein.");
return;
}
 
tracingService.Trace($"Fields count: {requestObject.Fields.Count}");
foreach (var field in requestObject.Fields)
{
tracingService.Trace($"Field: {field.Key} = {field.Value}");
}
 
var fieldsDict = requestObject.Fields.ToDictionary(f => f.Key, f => f.Value);
 
if (!fieldsDict.TryGetValue("nnc_event_registration_id", out string registrationCode) || string.IsNullOrWhiteSpace(registrationCode))
{
tracingService.Trace("nnc_event_registration_id not provided.");
SetValidationResponse(context, false, "Bitte geben Sie einen Einladungscode ein.");
return;
}
 
tracingService.Trace($"Registration code received: {registrationCode}");
 
var query = new QueryExpression("nnc_einladungsversand_empfanger")
{
ColumnSet = new ColumnSet("nnc_registration_abgeschlossen"),
Criteria = new FilterExpression
{
Conditions = {
new ConditionExpression("nnc_name", ConditionOperator.Equal, registrationCode)
}
}
};
 
tracingService.Trace("Executing query against nnc_einladungsversand_empfanger.");
var results = service.RetrieveMultiple(query);
 
if (results == null || !results.Entities.Any())
{
tracingService.Trace("Invitation code not valid.");
SetValidationResponse(context, false, "Dies ist kein gültiger Einladungscode.");
return;
}
 
var empfaenger = results.Entities.First();
var registrationCompleted = empfaenger.GetAttributeValue<bool>("nnc_registration_abgeschlossen");
 
tracingService.Trace($"Registration completed status: {registrationCompleted}");
 
if (registrationCompleted)
{
tracingService.Trace("Invitation code already registered.");
SetValidationResponse(context, false, "Für diesen Code wurde bereits eine Registration durchgeführt.");
return;
}
 
tracingService.Trace("Invitation code valid. Allowing registration.");
SetValidationResponse(context, true);
}
catch (Exception ex)
{
tracingService.Trace($"Exception occurred: {ex.Message}");
throw new InvalidPluginExecutionException("An error occurred during registration validation.", ex);
}
}
 
private void SetValidationResponse(IPluginExecutionContext context, bool isValid, string errorMessage = null)
{
 
 
//////// I think this is a critical part ///////////////////////
 
var resp = new ValidateFormSubmissionResponse()
{
IsValid = isValid,
ValidationOnlyFields = new List<string> { "nnc_event_registration_id" },
ValidationErrorMessage = string.IsNullOrEmpty(errorMessage) ? null : errorMessage
};
context.OutputParameters["msdynmkt_validationresponse"] = Serialize(resp);
}
 
////////////////////////////////////////////////////////////////
 
private T Deserialize<T>(string jsonString)
{
var serializer = new DataContractJsonSerializer(typeof(T));
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
{
return (T)serializer.ReadObject(stream);
}
}
 
private string Serialize<T>(T obj)
{
var serializer = new DataContractJsonSerializer(typeof(T));
using (var memoryStream = new MemoryStream())
{
serializer.WriteObject(memoryStream, obj);
return Encoding.UTF8.GetString(memoryStream.ToArray());
}
}
 
[DataContract]
public class FormSubmissionRequest
{
[DataMember(Name = "Fields")]
public List<FieldEntry> Fields { get; set; }
 
[DataMember(Name = "recordId")]
public string RecordId { get; set; }
 
[DataMember(Name = "submissionId")]
public string SubmissionId { get; set; }
 
[DataMember(Name = "entityName")]
public string EntityName { get; set; }
}
 
[DataContract]
public class FieldEntry
{
[DataMember(Name = "Key")]
public string Key { get; set; }
 
[DataMember(Name = "Value")]
public string Value { get; set; }
}
 
[DataContract]
public class ValidateFormSubmissionResponse
{
[DataMember(Name = "isValid")]
public bool IsValid { get; set; }
 
[DataMember(Name = "validationOnlyFields")]
public List<string> ValidationOnlyFields { get; set; }
 
[DataMember(Name = "validationErrorMessage", EmitDefaultValue = false)]
public string ValidationErrorMessage { get; set; }
}
}
}
 
 

Thanks in advance!

I have the same question (1)
  • Suggested answer
    Daivat Vartak (v-9davar) Profile Picture
    7,835 Super User 2025 Season 2 on at
    Hello JB-28042021-0,
     

    You've done a thorough job with the plugin logic and tracing! The issue you're facing, where the form fails to submit even with IsValid = true, likely lies in how you're setting the ValidationOnlyFields.

    The Key Insight: ValidationOnlyFields and Full Submission Control

    Your suspicion is correct. If you want to control the entire form submission (either allow it or block it), you should NOT be setting ValidationOnlyFields.

    Here's why:

    • Purpose of ValidationOnlyFields: This property is specifically designed for scenarios where you want to perform server-side validation on certain fields without blocking the entire form submission. The results of the validation for these fields can then be used to display inline error messages next to those specific fields on the form. The form submission itself will still proceed.

    • Impact on Full Submission: When you set ValidationOnlyFields, you are telling the Real-time Marketing form that you are only validating those specific fields and that the overall submission process should continue regardless of the IsValid value. This explains why your form is failing to submit even when IsValid is true – the form is not looking at IsValid to determine whether to proceed with the full submission because you've indicated you're only doing field-level validation.

       


    •  

    The Solution: Remove ValidationOnlyFields for Full Submission Control

    To achieve your goal of either blocking the form submission with a general error message or allowing it to proceed normally based on the validity of your nnc_event_registration_id, you need to modify your SetValidationResponse method as follows:

    private void SetValidationResponse(IPluginExecutionContext context, bool isValid, string errorMessage = null)
    {
        var resp = new ValidateFormSubmissionResponse()
        {
            IsValid = isValid,
            ValidationErrorMessage = string.IsNullOrEmpty(errorMessage) ? null : errorMessage
            // DO NOT SET ValidationOnlyFields here if you want to control full submission
        };
        context.OutputParameters["msdynmkt_validationresponse"] = Serialize(resp);
    }

     

    Explanation of the Change:

    By removing the line ValidationOnlyFields = new List<string> { "nnc_event_registration_id" };, you are now telling the Real-time Marketing form that your plugin's validation response (msdynmkt_validationresponse) should be used to determine the overall success or failure of the form submission.

    • IsValid = true (and ValidationOnlyFields is NOT set): The form submission will be considered successful and will proceed with the standard submission process.

    • IsValid = false (and ValidationOnlyFields is NOT set): The form submission will fail, and the ValidationErrorMessage (if provided) will be displayed to the user as a general submission error.


    •  

    Regarding Your Specific Questions:

    • Do I even need to set ValidationOnlyFields if I just want to block or allow the full form submission based on a simple yes/no validation? No, you should not set ValidationOnlyFields in this scenario. Setting it tells the form you're only validating those specific fields, not controlling the overall submission.

    • Could ValidationOnlyFields cause the form to behave differently, e.g., preventing full submission even if IsValid = true? Yes, as explained above, setting ValidationOnlyFields signals that you are only performing field-level validation, and the form's submission process will likely proceed regardless of the IsValid value in the context of the full submission. The error message you're seeing is the generic "there was an error with the submission" because the form isn't looking at IsValid to decide whether the entire submission is valid.

       


    •  

    In summary, the fix is to remove the ValidationOnlyFields assignment in your SetValidationResponse method when you want your plugin to control the success or failure of the entire form submission. Your plugin logic for checking the registration code and setting IsValid and ValidationErrorMessage is correct for this purpose.

     
    If my answer was helpful, please click Like, and if it solved your problem, please mark it as verified to help other community members find more. If you have further questions, please feel free to contact me.
     
    My response was crafted with AI assistance and tailored to provide detailed and actionable guidance for your Microsoft Dynamics 365 query.
     
    Regards,
    Daivat Vartak
  • JB-28042021-0 Profile Picture
    18 on at
    HI @Daivat Vartak (v-9davar), Unfortunately this is not the solution , still get Errors and the form is not submitted:

    Browser Log:

    Script form-loader-script loaded successfully.

    Logger.ts:7 Forms loaded

    Logger.ts:19 Form type is marketing form

    e.error @ Logger.ts:19

    (Internal Server Error)

  • Andrei G Profile Picture
    4 on at
    Hello, 
     
    I have the same issue. The suggestions in this post did not help yet. My form is always submitted, even if variable "isValid" is false. Cannot make the validationErrorMessage appear on the form, if validation fails. 
    Anyone has another suggestion or idea ? 
  • Verified answer
    Sang Doan Profile Picture
    12 on at
    I’ve discovered that the message schema name used by the form is actually error, not validationErrorMessage. Updating this reference resolved the issue on my end.
     

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

News and Announcements

Season of Giving Solutions is Here!

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > Customer experience | Sales, Customer Insights, CRM

#1
Pallavi Phade Profile Picture

Pallavi Phade 98

#2
Tom_Gioielli Profile Picture

Tom_Gioielli 79 Super User 2025 Season 2

#3
TAHER Mehdi Profile Picture

TAHER Mehdi 48

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans