今天解决了web api中 patch方法的功能,patch方法是什么请自行百度
因为都没有提供原生的解决方案,所以每个人解决的思路各不相同。
我解决的思路是,前台不修改原有数据结构,只需要传入需要修改的值,其它不可以不传。
然后后台先用id查询出整体的实体,然后通过反射遍历前台传入的实体,数据不为null的就取出来,赋值到后台的实体上,最后同put方法一样修改整体实体。
虽然这个方法看上去有点low,但是思路很清楚,不会很乱。方法如下:
前台传入的json
1 { 2 "PatientId": "9047df37-d43d-485a-8eda-1cd0b8228655", 3 "Details": { 4 "FirstName": "a2222222", 5 "LastName": "c" 6 }, 7 "Anatomy": { 8 "BodyWeight": 22222 9 }, 10 "PersonalInfo": { 11 12 "EmailAddressPrimary": "cxd@a.com" 13 } 14 }
后台patch方法
1 [Route("api/patients/{id}")] 2 [HttpPatch] 3 public async Task<IHttpActionResult> Patch(Guid id, Patient patient) 4 { 5 try 6 { 7 //后台先用id查询出整体的实体 8 Patient indb_Patient = await PatientRepository.GetInstance().GetPatient(id); 9 //然后通过反射遍历前台传入的实体,数据不为null的就取出来,赋值到后台的实体上,最后同put方法一样修改整体实体 10 //这有一个小问题,如果前台想给这个值赋值为null就没办法实现了,因为数值为null会跳过 11 PatchConvertEntity.PatchConvertToEntity(patient, indb_Patient); 12 //因为怕前台不传ID所以赋值一下 13 indb_Patient.PatientId = id; 14 await PatientRepository.GetInstance().EditPatient(id, indb_Patient); 15 return StatusCode(HttpStatusCode.NoContent); 16 } 17 catch (Exception ex) 18 { 19 return BadRequest(ex.Message); 20 } 21 }
反射遍历实体类的方法:
1 public class PatchConvertEntity 2 { 3 public static void PatchConvertToEntity<T>(T sendT, T indb_T) 4 { 5 PropertyInfo[] send_propertyInfos = sendT.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); 6 PropertyInfo[] indb_propertyInfos = indb_T.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); 7 8 for (int i = 0; i < send_propertyInfos.Length; i++) 9 { 10 string sendName = send_propertyInfos[i].Name; 11 object sendValue = send_propertyInfos[i].GetValue(sendT, null); 12 // if send data is null ,it will next data 13 if (sendValue == null) 14 { 15 continue; 16 } 17 18 if (send_propertyInfos[i].PropertyType.IsValueType || send_propertyInfos[i].PropertyType.Name.StartsWith("String")) 19 { 20 indb_propertyInfos[i].SetValue(indb_T, sendValue); 21 } 22 else 23 { 24 object indbValue = indb_propertyInfos[i].GetValue(indb_T, null); 25 PatchConvertToEntity(sendValue, indbValue); 26 } 27 } 28 } 29 }
修改方法就不多写了,就是一个普通的修改方法
db.Entry(patient).State = EntityState.Modified;
db.SaveChanges();
实体类设计要注意一下:
Guid enum datetime 等类型,要设计可空,如果不可空,前台不传时会有默认值。
public Guid? PatientKeyId { get; set; } public Gender? Gender { get; set; } public DateTime? CreateTime { get; set; }
【这个功能自己测试了一下没有问题,还需要其它类的测试】