Problem Statement
I am trying to pass an instance of an Apex
type from LWC into an AuraEnabled
method. However, all of the attributes are coming through as null
.
MVR
Back End
public with sharing class MyController
{
@AuraEnabled(cacheable=true)
public static void doStuff(Model instance)
{
system.debug(JSON.serialize(instance));
// { "sampleAttribute": null }
}
public class Model
{
@AuraEnabled
public String sampleAttribute;
}
}
Front End
import doStuff from "@salesforce/apex/MyController.doStuff"
export default class MyComponent extends LightningElement {
...
const instance = {
sampleAttribute: "I am populated"
};
console.debug(instance);
// { sampleAttribute: "I am populated" }
doStuff({ instance })
.then(result => { ... })
.catch(error => { ... });
}
Question
Why are my attributes all cleared out by the time they arrive at the back end? They are clearly populated right before I send them. I even tried specifying each attribute via string key just to be sure that wasn't contributing to the problem, but it did not resolve the issue.
Workaround
For now I am using serialization to get the call to work.
Back End
@AuraEnabled(cacheable=true)
public static void doStuff(String payload)
{
doStuffWithModel((Model)JSON.deserialize(payload, Model.class));
}
public static void doStuffWithModel(Model instance)
{
// implementation
}
Front End
const instance = {
sampleAttribute: "I am populated"
};
doStuff({ instance })
.then(result => { ... })
.catch(error => { ... });
Expose Apex Methods to Lightning Web Components
To expose an Apex method to a Lightning web component, the method must be static and either global or public. Annotate the method with @AuraEnabled.…
These types are supported for input and output.
- Primitive—Boolean, Date, DateTime, Decimal, Double, Integer, Long, and String.
- sObject—standard and custom sObjects are both supported.
- Apex—an instance of an Apex class. (Most often a custom class.)
- Collection—a collection of any of the other types.
But the documentation clearly indicates use of Apex types is supported. Using JSON should not be necessary.
Best Answer
This fails because the Model class is an inner class. It is probably a bug, but we hit this a while back and found:
As per sfdcfox's comment, we most often saw an internal server error when trying to pass an instance of an inner class to an aura enabled method.
The documentation does say:
Whilst this appears to be for Aura code, the LWC documentation indicates LWC has the same behaviour (see the link for "Apex" in the section entitled "Expose Apex Methods to Lightning Web Components"). So whilst it is probably a bug, they have documented to say things can go wrong if you try to use inner classes.
Something else that can cause issues is the use of @AuraEnabled public attributes in your data object, which can be remedied by switching to public properties. This MAY allow you to keep the class as an inner class, but there's no guarantee this will work in all cases. Certainly changing your inner Model class to a top level one like the following will resolve any issues: