티스토리 뷰
WebAPI CRUD, Repository, PCL - Visual Studio 2013
kaki104 2013. 11. 29. 10:49PCLSample 솔루션에 WebAPI를 이용해서 CRUD 하는 셈플을 완성했다. (옛날에는 무지 쉽게 했었는데..으흠;;)
이번 솔루션은 단순히 CRUD 오퍼레이션을 하는 것이 아니라, Repository pattern을 이용하도록 만들었다. 거의 실사용하는 수준으로 만들어져있는 부분들이 있으니 잘 참고 하면 간단한 서비스는 쉽게 만들 것이라 생각한다.
1. PCLSample.DAL
* PersonModelMap.cs
Id필드에 Identity속성 추가 - 속성이 추가 되기 위해서는 PCLSample 데이터베이스를 삭제 하고 다시 실행해야 적용된다.
class PersonModelMap : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<PersonModel>
{
public PersonModelMap()
{
this.HasKey(f => f.Id);
this.ToTable("People");
this.Property(f => f.Id)
.IsRequired()
.HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)
.HasColumnName("Id");
this.Property(f => f.Name)
.HasMaxLength(50)
.HasColumnName("Name");
this.Property(f => f.Age)
.HasColumnName("Age");
this.Property(f => f.Sex)
.HasColumnName("Sex");
}
}
* GenericRepository.cs
Update를 호출할 때 key를 함께 넘겨주어 처리하도록 수정
/// <summary>
/// Entity를 받아서 수정
/// </summary>
/// <param name="entityToUpdate"></param>
public virtual void Update(TEntity entityToUpdate, object key = null)
{
var entry = _context.Entry(entityToUpdate);
if(key == null)
key = this.GetPrimaryKey(entry);
if (entry.State == EntityState.Detached)
{
var currentEntry = _dbSet.Find(key);
if (currentEntry != null)
{
var attachedEntry = _context.Entry(currentEntry);
attachedEntry.CurrentValues.SetValues(entityToUpdate);
}
else
{
_dbSet.Attach(entityToUpdate);
entry.State = EntityState.Modified;
}
}
}
구글에서 찾아서 추가를 했는데..실제로 동작은 않되는 것 같다.
private object GetPrimaryKey(DbEntityEntry entry)
{
var myObject = entry.Entity;
var property = myObject.GetType()
.GetProperties()
.FirstOrDefault(prop => Attribute.IsDefined(prop, typeof(KeyAttribute)));
if (property == null)
return null;
return property.GetValue(myObject, null);
}
* IGenericRepository.cs
public interface IGenericRepository<TEntity>
where TEntity : class
{
System.Linq.IQueryable<TEntity> AllGetting();
void Delete(object id);
void Delete(TEntity entityToDelete);
void Detach(TEntity entityToDetach);
void Dispose();
System.Linq.IQueryable<TEntity> Getting(System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = null, Func<System.Linq.IQueryable<TEntity>, System.Linq.IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "", int? page = null, int? pageSize = null);
TEntity GettingByID(object id);
void Insert(TEntity entity);
void Update(TEntity entityToUpdate, object key = null);
}
2. PCLSample.WebAPI
StartPage.html을 하나 추가해서, 시작페이지로 지정했다. 아무래도 뭔가 나오는 것이 좋다.
* PeopleController.cs
Repository pattern을 사용하는 컨트롤러는 자동생성이 않되기 때문에 수동으로 작업해 준다.
public class PeopleController : ApiController
{
private IUnitOfWork _uow;
public PeopleController()
{
_uow = GlobalVariables.Container.Resolve<IUnitOfWork>();
}
/// <summary>
/// 조회 여러개
/// </summary>
/// <returns></returns>
[Queryable]
public IQueryable<PersonModel> GetPeople()
{
return _uow.PeopleRepo.AllGetting();
}
/// <summary>
/// 조회 1개
/// </summary>
public PersonModel GetPeople(int Id)
{
return _uow.PeopleRepo.GettingByID(Id);
}
/// <summary>
/// 수정
/// </summary>
/// <param name="id"></param>
/// <param name="person"></param>
/// <returns></returns>
public HttpResponseMessage PutPeople(int id, PersonModel person)
{
if (ModelState.IsValid && id == person.Id)
{
_uow.PeopleRepo.Update(person, id);
_uow.Save();
return Request.CreateResponse(HttpStatusCode.OK);
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
/// <summary>
/// 등록
/// </summary>
/// <param name="person"></param>
/// <returns></returns>
public HttpResponseMessage PostPeople(PersonModel person)
{
if (ModelState.IsValid)
{
_uow.PeopleRepo.Insert(person);
_uow.Save();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, person);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = person.Id }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
/// <summary>
/// 삭제
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public HttpResponseMessage DeletePeople(int id)
{
var existItem = _uow.PeopleRepo.GettingByID(id);
if (existItem == null)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
_uow.PeopleRepo.Delete(existItem);
_uow.Save();
return Request.CreateResponse(HttpStatusCode.OK, existItem);
}
}
3. PCLSample.PCL
* WebAPIBase.cs
public abstract class WebAPIBase<T> : BindableBase
{
/// <summary>
/// 베이스Uri
/// </summary>
public string BaseUri { get; set; }
/// <summary>
/// 서비스 Uri
/// </summary>
public string ServiceUri { get; set; }
/// <summary>
/// 결과코드
/// </summary>
public string ResultCode { get; set; }
/// <summary>
/// 결과메시지
/// </summary>
public string ResultMsg { get; set; }
/// <summary>
/// 반환갯수
/// </summary>
protected int NumOfRows { get; set; }
private int pageNo;
/// <summary>
/// 페이지 번호
/// </summary>
public int PageNo
{
get { return pageNo; }
set
{
pageNo = value;
OnPropertyChanged();
}
}
private int totalCount;
/// <summary>
/// 전체 카운트
/// </summary>
public int TotalCount
{
get { return totalCount; }
set
{
totalCount = value;
OnPropertyChanged();
}
}
/// <summary>
/// 토탈 페이지 = totalCount / NumOfRows + 1
/// </summary>
public int TotalPage { get; set; }
private bool isBusy;
/// <summary>
/// 작업중 여부
/// </summary>
public bool IsBusy
{
get { return isBusy; }
set { isBusy = value; OnPropertyChanged(); }
}
/// <summary>
/// 생성자
/// </summary>
public WebAPIBase()
{
BaseUri = "";
ServiceUri = "";
NumOfRows = 30;
PageNo = 1;
this.PropertyChanged +=
(s, e) =>
{
switch (e.PropertyName)
{
case "NumOfRows":
case "TotalCount":
if (TotalCount > 0 && NumOfRows > 0)
{
TotalPage = TotalCount / NumOfRows;
if ((TotalCount % NumOfRows) > 0)
TotalPage++;
}
else
{
TotalPage = 0;
}
break;
}
};
}
/// <summary>
/// 조회
/// </summary>
public async Task<string> GetData(string requestUri)
{
string result = string.Empty;
IsBusy = true;
using (HttpClient hc = new HttpClient())
{
try
{
//타임아웃30초
hc.Timeout = new TimeSpan(0, 0, 30);
var uri = string.Format("{0}{1}{2}", BaseUri, ServiceUri, requestUri);
result = await hc.GetStringAsync(uri);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
IsBusy = false;
}
}
IsBusy = false;
return result;
}
/// <summary>
/// 조회 목록
/// </summary>
public async Task<IList<T>> GetDatas(string requestUri)
{
IList<T> returnValue = new List<T>();
IsBusy = true;
using (HttpClient hc = new HttpClient())
{
try
{
hc.Timeout = new TimeSpan(0, 0, 30);
var uri = string.Format("{0}{1}{2}", BaseUri, ServiceUri, requestUri);
var result = await hc.GetAsync(uri);
if (result.IsSuccessStatusCode == true)
{
var data = await result.Content.ReadAsStringAsync();
if (data != null)
{
returnValue = JsonConvert.DeserializeObject<List<T>>(data);
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
IsBusy = false;
}
}
IsBusy = false;
return returnValue;
}
/// <summary>
/// 등록
/// </summary>
/// <param name="postItem"></param>
/// <returns></returns>
public virtual async Task<T> PostAsync(T postItem)
{
T returnValue = default(T);
if (postItem != null)
{
var json = JsonConvert.SerializeObject(postItem);
if (json != null && json.Length > 0)
{
using (var hc = new HttpClient())
{
var sc = new StringContent(json, Encoding.UTF8, "application/json");
try
{
var uri = string.Format("{0}{1}", BaseUri, ServiceUri);
var resp = await hc.PostAsync(uri, sc);
if (resp.IsSuccessStatusCode == true)
{
var content = await resp.Content.ReadAsStringAsync();
returnValue = JsonConvert.DeserializeObject<T>(content);
}
}
catch (Exception ex)
{
#if DEBUG
System.Diagnostics.Debug.WriteLine(ex.Message);
throw;
#endif
}
}
}
}
return returnValue;
}
/// <summary>
/// 수정
/// </summary>
/// <param name="putItem"></param>
/// <returns></returns>
public virtual async Task<bool> PutAsync(T putItem, object key)
{
bool returnValue = false;
var json = JsonConvert.SerializeObject(putItem);
if (json != null && json.Length > 0)
{
using (var hc = new HttpClient())
{
var sc = new StringContent(json, Encoding.UTF8, "application/json");
var uri = string.Format("{0}{1}{2}", BaseUri, ServiceUri, key.ToString());
try
{
var resp = await hc.PutAsync(uri, sc);
if (resp.IsSuccessStatusCode == true)
{
returnValue = true;
}
}
catch (Exception ex)
{
#if DEBUG
System.Diagnostics.Debug.WriteLine(ex.Message);
throw;
#endif
}
}
}
return returnValue;
}
/// <summary>
/// 삭제
/// </summary>
/// <param name="deleteItem"></param>
/// <returns></returns>
public virtual async Task<bool> DeleteAsync(T deleteItem, object key)
{
bool returnValue = false;
using (var hc = new HttpClient())
{
var query = string.Format("{0}{1}{2}", BaseUri, ServiceUri, key.ToString());
try
{
var resp = await hc.DeleteAsync(query);
if (resp.IsSuccessStatusCode)
{
returnValue = true;
}
}
catch (Exception ex)
{
#if DEBUG
System.Diagnostics.Debug.WriteLine(ex.Message);
throw;
#endif
}
}
return returnValue;
}
}
* PersonHelper.cs
public class PersonHelper : WebAPIBase<PersonModel>
{
/// <summary>
/// 인스턴스
/// </summary>
private readonly static PersonHelper instance = new PersonHelper();
/// <summary>
/// 인스턴스 프로퍼티
/// </summary>
public static PersonHelper Instance
{
get
{
return instance;
}
}
/// <summary>
/// 생성자
/// </summary>
public PersonHelper()
: base()
{
BaseUri = "http://localhost:59409";
ServiceUri = "/api/People/";
}
}
* MainViewModel.cs
private DelegateCommand _getListCommand;
public DelegateCommand GetListCommand
{
get
{
return _getListCommand = _getListCommand ?? new DelegateCommand(
async para =>
{
var result = await PersonHelper.Instance.GetDatas("");
People = new ObservableCollection<PersonModel>(result);
});
}
}
private DelegateCommand _newCommand;
public DelegateCommand NewCommand
{
get
{
return _newCommand = _newCommand ?? new DelegateCommand(
para =>
{
Person = new PersonModel();
People.Add(Person);
});
}
}
private DelegateCommand _updateCommand;
public DelegateCommand UpdateCommand
{
get
{
return _updateCommand = _updateCommand ?? new DelegateCommand(
async para =>
{
if (Person == null) return;
if (Person.Id == 0)
{
var newPerson = await PersonHelper.Instance.PostAsync(Person);
Person.Id = newPerson.Id;
}
else
{
var update = await PersonHelper.Instance.PutAsync(Person, Person.Id);
}
});
}
}
private DelegateCommand _deleteCommand;
public DelegateCommand DeleteCommand
{
get
{
return _deleteCommand = _deleteCommand ?? new DelegateCommand(
async para =>
{
if (Person != null)
{
var result = await PersonHelper.Instance.DeleteAsync(Person, Person.Id);
if (result == true)
{
People.Remove(Person);
Person = null;
}
}
});
}
}
4. PCLSample.WPF
2군데 수정
* MainWindow.xaml, MainWindow.xaml.cs
실버라이트 프로젝트와 Store app 프로젝트는 직접 수정하도록 한다.
5. 솔루션 프로퍼티에서 시작 프로젝트를 2개로 지정한다.
F5로 실행하면 아래와 같이 2개의 창이 뜬다.
6. 오퍼레이션
Id 5번을 선택 한 후
Name : kaki110, Age : 30으로 수정 후 Update
New 클릭 -> Name : kaki120, Age : 33, Sex : uncheck -> Update 클릭
Id 3번 선택 후 Delete를 클릭
전체 소스
'Previous Platforms > HTML5 & MVC4' 카테고리의 다른 글
Individual Accounts in ASP.NET Web API - Visual Studio 2013 (0) | 2013.12.05 |
---|---|
Supporting OData Query Options - Visual Studio 2013 (0) | 2013.11.28 |
Creating an OData Endpoint in ASP.NET Web API - Visual Studio 2013 (0) | 2013.11.27 |
OData Endpoint with ASP.NET Web API Part3 - Clients (0) | 2013.10.15 |
OData Endpoint with ASP.NET Web API Part2 - Web (0) | 2013.10.15 |
- Total
- Today
- Yesterday
- #uwp
- Windows 10
- Build 2016
- #MVVM
- uno platform
- WPF
- ComboBox
- dotNETconf
- Visual Studio 2022
- Microsoft
- #prism
- C#
- .net 5.0
- Always Encrypted
- Cross-platform
- visual studio 2019
- uno-platform
- IOT
- ef core
- UWP
- Bot Framework
- windows 11
- Behavior
- PRISM
- LINQ
- XAML
- .net
- kiosk
- #Windows Template Studio
- MVVM
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |