Skip to content

Commit 4d0d422

Browse files
committed
added ValidateModelState as feature flag in options
1 parent 9d16115 commit 4d0d422

File tree

3 files changed

+60
-5
lines changed

3 files changed

+60
-5
lines changed

Diff for: src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs

+10
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,16 @@ public class JsonApiOptions
125125
/// </remarks>
126126
public bool EnableOperations { get; set; }
127127

128+
/// <summary>
129+
/// Whether or not to validate model state.
130+
/// </summary>
131+
/// <example>
132+
/// <code>
133+
/// options.ValidateModelState = true;
134+
/// </code>
135+
/// </example>
136+
public bool ValidateModelState { get; set; }
137+
128138
[Obsolete("JsonContract resolver can now be set on SerializerSettings.")]
129139
public IContractResolver JsonContractResolver
130140
{

Diff for: src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public virtual async Task<IActionResult> PostAsync([FromBody] T entity)
153153

154154
if (!_jsonApiContext.Options.AllowClientGeneratedIds && !string.IsNullOrEmpty(entity.StringId))
155155
return Forbidden();
156-
if (!ModelState.IsValid)
156+
if (_jsonApiContext.Options.ValidateModelState && !ModelState.IsValid)
157157
return BadRequest(ModelState.ConvertToErrorCollection());
158158

159159
entity = await _create.CreateAsync(entity);
@@ -167,7 +167,7 @@ public virtual async Task<IActionResult> PatchAsync(TId id, [FromBody] T entity)
167167

168168
if (entity == null)
169169
return UnprocessableEntity();
170-
if (!ModelState.IsValid)
170+
if (_jsonApiContext.Options.ValidateModelState && !ModelState.IsValid)
171171
return BadRequest(ModelState.ConvertToErrorCollection());
172172

173173
var updatedEntity = await _update.UpdateAsync(id, entity);

Diff for: test/UnitTests/Controllers/BaseJsonApiController_Tests.cs

+48-3
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ public async Task PatchAsync_Calls_Service()
146146
const int id = 0;
147147
var resource = new Resource();
148148
var serviceMock = new Mock<IUpdateService<Resource>>();
149+
_jsonApiContextMock.Setup(a => a.ApplyContext<Resource>(It.IsAny<BaseJsonApiController<Resource>>())).Returns(_jsonApiContextMock.Object);
150+
_jsonApiContextMock.SetupGet(a => a.Options).Returns(new JsonApiOptions());
149151
var controller = new BaseJsonApiController<Resource>(_jsonApiContextMock.Object, update: serviceMock.Object);
150152

151153
// act
@@ -157,12 +159,34 @@ public async Task PatchAsync_Calls_Service()
157159
}
158160

159161
[Fact]
160-
public async Task PatchAsync_ModelStateInvalid()
162+
public async Task PatchAsync_ModelStateInvalid_ValidateModelStateDisbled()
163+
{
164+
// arrange
165+
const int id = 0;
166+
var resource = new Resource();
167+
var serviceMock = new Mock<IUpdateService<Resource>>();
168+
_jsonApiContextMock.Setup(a => a.ApplyContext<Resource>(It.IsAny<BaseJsonApiController<Resource>>())).Returns(_jsonApiContextMock.Object);
169+
_jsonApiContextMock.SetupGet(a => a.Options).Returns(new JsonApiOptions { ValidateModelState = false });
170+
var controller = new BaseJsonApiController<Resource>(_jsonApiContextMock.Object, update: serviceMock.Object);
171+
172+
// act
173+
var response = await controller.PatchAsync(id, resource);
174+
175+
// assert
176+
serviceMock.Verify(m => m.UpdateAsync(id, It.IsAny<Resource>()), Times.Once);
177+
VerifyApplyContext();
178+
Assert.IsNotType<BadRequestObjectResult>(response);
179+
}
180+
181+
[Fact]
182+
public async Task PatchAsync_ModelStateInvalid_ValidateModelStateEnabled()
161183
{
162184
// arrange
163185
const int id = 0;
164186
var resource = new Resource();
165187
var serviceMock = new Mock<IUpdateService<Resource>>();
188+
_jsonApiContextMock.Setup(a => a.ApplyContext<Resource>(It.IsAny<BaseJsonApiController<Resource>>())).Returns(_jsonApiContextMock.Object);
189+
_jsonApiContextMock.SetupGet(a => a.Options).Returns(new JsonApiOptions{ValidateModelState = true});
166190
var controller = new BaseJsonApiController<Resource>(_jsonApiContextMock.Object, update: serviceMock.Object);
167191
controller.ModelState.AddModelError("Id", "Failed Validation");
168192

@@ -211,13 +235,34 @@ public async Task PostAsync_Calls_Service()
211235
}
212236

213237
[Fact]
214-
public async Task PostAsync_ModelStateInvalid()
238+
public async Task PostAsync_ModelStateInvalid_ValidateModelStateDisabled()
215239
{
216240
// arrange
217241
var resource = new Resource();
218242
var serviceMock = new Mock<ICreateService<Resource>>();
219243
_jsonApiContextMock.Setup(a => a.ApplyContext<Resource>(It.IsAny<BaseJsonApiController<Resource>>())).Returns(_jsonApiContextMock.Object);
220-
_jsonApiContextMock.SetupGet(a => a.Options).Returns(new JsonApiOptions());
244+
_jsonApiContextMock.SetupGet(a => a.Options).Returns(new JsonApiOptions { ValidateModelState = false });
245+
var controller = new BaseJsonApiController<Resource>(_jsonApiContextMock.Object, create: serviceMock.Object);
246+
serviceMock.Setup(m => m.CreateAsync(It.IsAny<Resource>())).ReturnsAsync(resource);
247+
controller.ControllerContext = new Microsoft.AspNetCore.Mvc.ControllerContext { HttpContext = new DefaultHttpContext() };
248+
249+
// act
250+
var response = await controller.PostAsync(resource);
251+
252+
// assert
253+
serviceMock.Verify(m => m.CreateAsync(It.IsAny<Resource>()), Times.Once);
254+
VerifyApplyContext();
255+
Assert.IsNotType<BadRequestObjectResult>(response);
256+
}
257+
258+
[Fact]
259+
public async Task PostAsync_ModelStateInvalid_ValidateModelStateEnabled()
260+
{
261+
// arrange
262+
var resource = new Resource();
263+
var serviceMock = new Mock<ICreateService<Resource>>();
264+
_jsonApiContextMock.Setup(a => a.ApplyContext<Resource>(It.IsAny<BaseJsonApiController<Resource>>())).Returns(_jsonApiContextMock.Object);
265+
_jsonApiContextMock.SetupGet(a => a.Options).Returns(new JsonApiOptions { ValidateModelState = true });
221266
var controller = new BaseJsonApiController<Resource>(_jsonApiContextMock.Object, create: serviceMock.Object);
222267
controller.ModelState.AddModelError("Id", "Failed Validation");
223268

0 commit comments

Comments
 (0)