Skip to content

Conversation

@paorodma-ms
Copy link
Contributor

Description

Block update for a spec defined parameter. Changed DeleteSearchParamBehavior to check if it is a system defined search parameter or if it doesn't exist to return correct response codes. Included related tests.

Related issues

Addresses https://microsofthealth.visualstudio.com/Health/_workitems/edit/179097.

Testing

Tested with rest api calls and unit tests.

FHIR Team Checklist

  • Update the title of the PR to be succinct and less than 65 characters
  • Add a milestone to the PR for the sprint that it is merged (i.e. add S47)
  • Tag the PR with the type of update: Bug, Build, Dependencies, Enhancement, New-Feature or Documentation
  • Tag the PR with Open source, Azure API for FHIR (CosmosDB or common code) or Azure Healthcare APIs (SQL or common code) to specify where this change is intended to be released.
  • Tag the PR with Schema Version backward compatible or Schema Version backward incompatible or Schema Version unchanged if this adds or updates Sql script which is/is not backward compatible with the code.
  • When changing or adding behavior, if your code modifies the system design or changes design assumptions, please create and include an ADR.
  • CI is green before merge Build Status
  • Review squash-merge requirements

Semver Change (docs)

Patch|Skip|Feature|Breaking (reason)

@paorodma-ms paorodma-ms added this to the FY26\Q2\2Wk\2Wk13 milestone Dec 19, 2025
@paorodma-ms paorodma-ms self-assigned this Dec 19, 2025
@paorodma-ms paorodma-ms requested a review from a team as a code owner December 19, 2025 23:17
@paorodma-ms paorodma-ms added Bug Bug bug bug. Azure API for FHIR Label denotes that the issue or PR is relevant to the Azure API for FHIR Azure Healthcare APIs Label denotes that the issue or PR is relevant to the FHIR service in the Azure Healthcare APIs Schema Version unchanged labels Dec 19, 2025
public async Task GivenADeleteResourceRequest_WhenDeletingASystemDefinedSearchParameterResource_ThenDeleteSearchParameterShouldNotBeCalled()
{
var searchParameter = new SearchParameter() { Id = "system-param", Url = "http://hl7.org/fhir/SearchParameter/system-param" };
var resource = searchParameter.ToTypedElement().ToResourceElement();

Check warning

Code scanning / CodeQL

Useless assignment to local variable Warning

This assignment to
resource
is useless, since its value is never read.

Copilot Autofix

AI 4 days ago

In general, to fix a “useless assignment to local variable” you either remove the unnecessary variable/assignment, or, if the result was actually meant to be used, you update the code to use it appropriately. Since resource is never read in this test, the simplest and safest change is to remove the unused local variable and its assignment, without altering any behavior of the test.

Concretely, in src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Search/SearchParameters/SearchParameterBehaviorTests.cs, inside the method GivenADeleteResourceRequest_WhenDeletingASystemDefinedSearchParameterResource_ThenDeleteSearchParameterShouldNotBeCalled, remove the line:

var resource = searchParameter.ToTypedElement().ToResourceElement();

No additional imports, methods, or definitions are needed, and no other lines in that method depend on resource, so no further changes are required.

Suggested changeset 1
src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Search/SearchParameters/SearchParameterBehaviorTests.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Search/SearchParameters/SearchParameterBehaviorTests.cs b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Search/SearchParameters/SearchParameterBehaviorTests.cs
--- a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Search/SearchParameters/SearchParameterBehaviorTests.cs
+++ b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Search/SearchParameters/SearchParameterBehaviorTests.cs
@@ -163,7 +163,6 @@
         public async Task GivenADeleteResourceRequest_WhenDeletingASystemDefinedSearchParameterResource_ThenDeleteSearchParameterShouldNotBeCalled()
         {
             var searchParameter = new SearchParameter() { Id = "system-param", Url = "http://hl7.org/fhir/SearchParameter/system-param" };
-            var resource = searchParameter.ToTypedElement().ToResourceElement();
 
             var key = new ResourceKey("SearchParameter", "system-param");
             var request = new DeleteResourceRequest(key, DeleteOperation.SoftDelete);
EOF
@@ -163,7 +163,6 @@
public async Task GivenADeleteResourceRequest_WhenDeletingASystemDefinedSearchParameterResource_ThenDeleteSearchParameterShouldNotBeCalled()
{
var searchParameter = new SearchParameter() { Id = "system-param", Url = "http://hl7.org/fhir/SearchParameter/system-param" };
var resource = searchParameter.ToTypedElement().ToResourceElement();

var key = new ResourceKey("SearchParameter", "system-param");
var request = new DeleteResourceRequest(key, DeleteOperation.SoftDelete);
Copilot is powered by AI and may make mistakes. Always verify output.
{
private ISearchParameterOperations _searchParameterOperations;
private IFhirDataStore _fhirDataStore;
private ISearchParameterDefinitionManager _searchParameterDefinitionManager;

Check notice

Code scanning / CodeQL

Missed 'readonly' opportunity Note

Field '_searchParameterDefinitionManager' can be 'readonly'.

Copilot Autofix

AI about 5 hours ago

In general, to fix a “Missed readonly opportunity” warning, you add the readonly modifier to any field that is only assigned at its declaration or within constructors of the same class, and never reassigned elsewhere. This ensures the field cannot be changed after the object is fully constructed.

For this specific case, the best fix is to add readonly to the three private dependency fields in DeleteSearchParameterBehavior<TDeleteResourceRequest, TDeleteResourceResponse> that are assigned in the constructor and then only read: _searchParameterOperations, _fhirDataStore, and _searchParameterDefinitionManager. Although CodeQL flagged only _searchParameterDefinitionManager, the same pattern applies to the other two fields, and marking all of them readonly improves consistency and clarity without changing behavior.

Concretely, in src/Microsoft.Health.Fhir.Core/Features/Search/Parameters/DeleteSearchParameterBehavior.cs, on lines 26–28, change:

private ISearchParameterOperations _searchParameterOperations;
private IFhirDataStore _fhirDataStore;
private ISearchParameterDefinitionManager _searchParameterDefinitionManager;

to:

private readonly ISearchParameterOperations _searchParameterOperations;
private readonly IFhirDataStore _fhirDataStore;
private readonly ISearchParameterDefinitionManager _searchParameterDefinitionManager;

No additional methods, imports, or definitions are required, since the rest of the code already uses these fields as immutable dependencies.

Suggested changeset 1
src/Microsoft.Health.Fhir.Core/Features/Search/Parameters/DeleteSearchParameterBehavior.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/Microsoft.Health.Fhir.Core/Features/Search/Parameters/DeleteSearchParameterBehavior.cs b/src/Microsoft.Health.Fhir.Core/Features/Search/Parameters/DeleteSearchParameterBehavior.cs
--- a/src/Microsoft.Health.Fhir.Core/Features/Search/Parameters/DeleteSearchParameterBehavior.cs
+++ b/src/Microsoft.Health.Fhir.Core/Features/Search/Parameters/DeleteSearchParameterBehavior.cs
@@ -23,9 +23,9 @@
     public class DeleteSearchParameterBehavior<TDeleteResourceRequest, TDeleteResourceResponse> : IPipelineBehavior<TDeleteResourceRequest, TDeleteResourceResponse>
         where TDeleteResourceRequest : DeleteResourceRequest, IRequest<TDeleteResourceResponse>
     {
-        private ISearchParameterOperations _searchParameterOperations;
-        private IFhirDataStore _fhirDataStore;
-        private ISearchParameterDefinitionManager _searchParameterDefinitionManager;
+        private readonly ISearchParameterOperations _searchParameterOperations;
+        private readonly IFhirDataStore _fhirDataStore;
+        private readonly ISearchParameterDefinitionManager _searchParameterDefinitionManager;
 
         public DeleteSearchParameterBehavior(
             ISearchParameterOperations searchParameterOperations,
EOF
@@ -23,9 +23,9 @@
public class DeleteSearchParameterBehavior<TDeleteResourceRequest, TDeleteResourceResponse> : IPipelineBehavior<TDeleteResourceRequest, TDeleteResourceResponse>
where TDeleteResourceRequest : DeleteResourceRequest, IRequest<TDeleteResourceResponse>
{
private ISearchParameterOperations _searchParameterOperations;
private IFhirDataStore _fhirDataStore;
private ISearchParameterDefinitionManager _searchParameterDefinitionManager;
private readonly ISearchParameterOperations _searchParameterOperations;
private readonly IFhirDataStore _fhirDataStore;
private readonly ISearchParameterDefinitionManager _searchParameterDefinitionManager;

public DeleteSearchParameterBehavior(
ISearchParameterOperations searchParameterOperations,
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
@jestradaMS jestradaMS self-assigned this Dec 23, 2025
Comment on lines 53 to 55
var systemDefinedParam = allSearchParameters.FirstOrDefault(sp =>
sp.IsSystemDefined &&
sp.Url.ToString().EndsWith($"/{deleteRequest.ResourceKey.Id}", StringComparison.OrdinalIgnoreCase));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using endswith could potentially grab the wrong entry. Might be more accurate to extract everything after last / and compare that to ResourceKey.id exactly.

Suggested change
var systemDefinedParam = allSearchParameters.FirstOrDefault(sp =>
sp.IsSystemDefined &&
sp.Url.ToString().EndsWith($"/{deleteRequest.ResourceKey.Id}", StringComparison.OrdinalIgnoreCase));
var systemDefinedParam = allSearchParameters.FirstOrDefault(sp =>
sp.IsSystemDefined &&
sp.Url?.Segments.LastOrDefault()?.TrimEnd('/') == deleteRequest.ResourceKey.Id);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Azure API for FHIR Label denotes that the issue or PR is relevant to the Azure API for FHIR Azure Healthcare APIs Label denotes that the issue or PR is relevant to the FHIR service in the Azure Healthcare APIs Bug Bug bug bug. Schema Version unchanged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants