Last active
August 29, 2015 14:28
-
-
Save gongdo/5105e7cf959f9f5f3307 to your computer and use it in GitHub Desktop.
Poor-man's partial update & validation in ASP.NET 5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[HttpPut] | |
public async Task<MyResult> Put(string id) | |
{ | |
// 일단 입력값(JSON)을 JObject로 읽기 | |
JObject jobject; | |
using (var sr = new StreamReader(Request.Body)) | |
{ | |
jobject = JObject.Load(new JsonTextReader(sr)); | |
} | |
// 업데이트 모델로 deserialize | |
var updateModel = jobject.ToObject<MyUpdateModel>(); | |
// deserialize된 모델로 ValidationContext를 준비 | |
var validationContext = new ValidationContext(updateModel); | |
// 입력된 JSON의 JProperty목록 뽑기 | |
var properties = jobject.Properties().Where(p => true /*!커스텀!불필요한 필드 필터링*/).ToList(); | |
var jpropertyAttribute = typeof(JsonPropertyAttribute); | |
// JProperty들중에서 업데이트 모델에 정의되어 있는 프로퍼티 목록만 매핑 | |
var mapping = updateModel.GetType() | |
.GetProperties() | |
.Where(p => p.CanRead && p.CanWrite) | |
.Select(p => | |
{ | |
// JsonProperty 어트리뷰트를 존중하여 프로퍼티 이름 비교 | |
var propertyName = p.GetCustomAttribute<JsonPropertyAttribute>(true)?.PropertyName ?? p.Name; | |
var jproperty = properties.FirstOrDefault(j => j.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)); | |
// 모델 새로 만들기 귀찮으니 Tuple로 때우기 | |
return new Tuple<JProperty, PropertyInfo>(jproperty, p); | |
}) | |
.Where(m => m.Item1 != null) // 매핑되지 않은 JProperty는 탈락 | |
.ToDictionary(m => m.Item1, m => m.Item2); | |
// 씐나게 살아남은 프로퍼티를 validate | |
foreach (var item in mapping) | |
{ | |
validationContext.MemberName = item.Value.Name; // 요놈이 컨텍스트내에서 지정한 멤버만 validate하는 핵심 | |
var value = item.Value.GetValue(updateModel); | |
Validator.ValidateProperty(value, validationContext); | |
} | |
// 여기까지 왔다면 mapping에 남아있는 프로퍼티는 전부다 유효한 이름/값임. | |
// 아래는 사용하는 Repository나 DB에 따라 적절하게 partial update 로직을 구현. | |
// 여기에서는 역시 귀찮으니 유효한 프로퍼티들만 json으로 serialize하고 끝. | |
// JProperty를 기준으로 serialize하는게 간편하긴 함. | |
// 반대로 mapping.Values를 사용하면 모델의 프로퍼티를 이용한 처리가 가능. | |
var json = JsonConvert.SerializeObject(new JObject(mapping.Keys)); | |
var result = UltimateMergeMachine.Merge(json); | |
return result; | |
} |
아... 깃헙 정도 되면 탭 간격도 조절 해줄거라고 생각했는데... 그렇군요.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
공백문자가 아닌 탭을 사용해서 그런 것 같네요. 공백을 사용해 들여쓰기할 때에는 (당연히) 잘 나옵니다.