Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot update MaxLength property on a text field #1541

Open
1 task done
tomasz-sintel opened this issue Sep 23, 2024 · 7 comments
Open
1 task done

Cannot update MaxLength property on a text field #1541

tomasz-sintel opened this issue Sep 23, 2024 · 7 comments
Assignees
Labels
area: model 📐 Related to the core SDK models question Further information is requested

Comments

@tomasz-sintel
Copy link

Category

  • Bug

Describe the bug

After retrieving fields from a list, I am trying to update some of their properties. I query the fields with the f => f.All include flag to have all of the props present. At the moment I am only interested in Single Line Text Field fields, so I filter them out. I can see the prop values loaded properly. I am able to update properties like Title, Required, Unique, Indexed successfully. But after I had added setting the MaxLength property, the code fails with a message:
The property 'MaxLength' does not exist on type 'SP.Field'. Make sure to only use property names that are defined by the type.

I am working with a batch to group multiple field updates into a single operation. But I have also tried to update each field individually with no success.

Steps to reproduce

var list = await context.Web.Lists.GetByIdAsync(listId);
var fields = await list.Fields.QueryProperties(f => f.All)
    .ToListAsync(cancellationToken);
var allFields = fields.ToList();

// get any single line text field by name or type
var field = fields.FirstOrDefault(f => f.FieldTypeKind == FieldType.Text);

// this batch does not make sense here, but I am working on multiple fields before pushing changes to server
var batch = context.NewBatch();
field.Required = true;
field.MaxLength = 120;
await field.UpdateBatchAsync(batch);

// this line throws the exception
await context.ExecuteAsync(batch);

Expected behavior

I expect the request not to fail :)

Environment details (development & target environment)

  • SDK version: 1.14.0
  • OS: Windows 11 Pro
  • SDK used in: ASP.Net Web app
  • Framework: .NET 8
  • Browser(s): N/A
  • Tooling: Visual Studio 2022
  • Additional details: N/A

Additional context

Exception details:
Message: SharePoint Rest service exception
Source: PnP.Core
StackTrace:

   at PnP.Core.Services.BatchClient.ProcessSharePointRestBatchResponseContent(Batch batch, String batchResponse, Dictionary`2 responseHeadersToPropagate)
   at PnP.Core.Services.BatchClient.<ProcessSharePointRestBatchResponse>d__54.MoveNext()
   at PnP.Core.Services.BatchClient.<ExecuteSharePointRestBatchAsync>d__52.MoveNext()
   at PnP.Core.Services.BatchClient.<ExecuteBatch>d__37.MoveNext()
   at PnP.Core.Services.PnPContext.<ExecuteAsync>d__101.MoveNext()
   at <obfuscated>.SharePoint.Infrastructure.FormStructure.FormStructureUpdater.<UpdatePreExistingFieldsAsync>d__9.MoveNext() in <obfuscated>.SharePoint\Infrastructure\FormStructure\FormStructureUpdater.cs:line 118

Inner Exception: null
Error (partial):
HttpResponseCode: 400
Message: The property 'MaxLength' does not exist on type 'SP.Field'. Make sure to only use property names that are defined by the type.
Type: SharePointRestServiceError
HResult: -2146233088

Additionally...

I have peeked the request data and the type of the field being updated in the request payload is set to SP.Field. I am not sure, but maybe this value should be set to the specific field's type, e.g. SP.FieldText. I have a suspicion that setting other field types' exclusive properties may lead to the same problem.

Thanks for your contribution! Sharing is caring.

@jansenbe
Copy link
Contributor

@tomasz-sintel : can you try updating the SchemaXmlWithResourceTokens property of the field. See #1418

@jansenbe jansenbe self-assigned this Sep 25, 2024
@jansenbe jansenbe added question Further information is requested area: model 📐 Related to the core SDK models labels Sep 25, 2024
@tomasz-sintel
Copy link
Author

tomasz-sintel commented Sep 25, 2024

@jansenbe There is no SchemaXmlWithResourceTokens property on the IField interface. I can update the value with the SchemaXml property, and that's what I had suspected. I didn't want to go that route though, because I was afraid of mixing the use of property setters and SchemaXml setter.

Consider the following piece of code:

public record XmlValue(string AttributeName, string Value);
// ...
// GetUpdatedSchemaXml is just an XML transformation method
field.SchemaXml = GetUpdatedSchemaXml(field.SchemaXml, new XmlValue("MaxLength", "123"));
field.Title = "Some Title";
field.EnforceUniqueValues = true;
field.Indexed = true;
field.Required = true;

await field.UpdateAsync();

In the example above the code only works if the SchemaXml is set as the first operation. If I move it below the field.Required = true; line, the EnforceUniqueValues is not updated in the field, although no error is thrown and the other props are set.

What is your recommendation? Is it safe to keep it as presented above or would I need to turn to setting ALL field props through the SchemaXml now?

From my colleague's experiment I know, that the problem is the same for any dedicated field properties in other field types, e.g. Min and Max props in a number field.

[UPDATE]
No, the other properties set after the SchemaXml do not update properly in the list field, sorry. So - the only choice I have is to go exclusively through SchemaXml?

@jansenbe
Copy link
Contributor

Like you mentioned in your initial comment, some more testing is needed with using the "right" type when building the update payload (would be a change in Core SDK). In the meantime please try with reading/updating/writing SchemaXML

@tomasz-sintel
Copy link
Author

Ok, thanks. I'll let you decide what to do with this bug.

@jansenbe
Copy link
Contributor

You've any feedback here @tomasz-sintel ?

@tomasz-sintel
Copy link
Author

Yes, from my side working with SchemaXml works provided that this property is used exclusively to set values on the field. My colleague came up with a workaround to make the individual properties work:

((Field)field).Metadata["type"] = "SP.FieldText";

It's suppose to work, but I haven't used it, since I already got it to work with the SchemaXml. The core reason as to why the type in the Metadata is always set to SP.Field is more complex and this is where I see the real fix of the issue. Unfortunately we do not have scope for this, especially when we got it to work in the end.

@RafalUrbanski
Copy link

Currently this code:
((Field)field).Metadata["type"] = "SP.FieldText";
will not work, as Field class is sealed and we cannot cast to it. During tests, I changed it's definition (removed the sealed modifier) and provided code worked. What we basically need is a way to change a Field.Metadata["type"] to appropriate type in order for the Update operation to work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: model 📐 Related to the core SDK models question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants