Edit a record in MVC multi layer - c#

I have a project with 8 layers
I want to edit a record ; for example:
In repository layer:
1:in IRepository:
IEnumerable GetArea(int id);
void Edit(CRM_Area crm);
2: in repository:
public IEnumerable<CRM_Area> GetArea(int ID)
{
return _db.CrmAreas.Where(x=>x.ID==ID);
}
public void Edit(CRM_Area crmArea)
{
_db.Entry(crmArea).State=EntityState.Modified;
}
and in services layer:
1:in Iservices:
void Delete(int ID);
IEnumerable<_CRM_AreaList> GetArea(int ID);
void Edit(_CRM_AreaEdit crmArea);
2: in Services:
public IEnumerable<_CRM_AreaList> GetArea(int ID)
{
return _areaRepository.GetArea(ID).Select(Mapper.Map<CRM_Area, _CRM_AreaList>);
}
public void Edit(_CRM_AreaEdit crmAreaEdit)
{
var editArea = Mapper.Map<_CRM_AreaEdit, CRM_Area>(crmAreaEdit);
_areaRepository.Edit(editArea);
}
and in web layer in controller:
[HttpGet]
public ActionResult Edit(int ID)
{
return View(_areaServices.GetArea(ID));
}
[HttpPost]
public ActionResult Edit(_CRM_AreaEdit crmAreaEdit)
{
_areaServices.Edit(crmAreaEdit);
return RedirectToAction("List");
}
But it doesn't work. Please help me - How can I edit and where is my mistake?
When I click on edit, the model item passed into the dictionary is of type 'System.Linq.Enumerable+WhereSelectEnumerableIterator`2[CRM.Web.Models.CRM_Area,CRM.Web.ViewModel.Area._CRM_AreaList]', but this dictionary requires a model item of type 'CRM.Web.ViewModel.Area._CRM_AreaEdit'.

In your repository try to save the changes.
Always keep in mind, you need to save the changes after you edit it.
public void Edit(CRM_Area crmArea)
{
_db.Entry(crmArea).State=EntityState.Modified;
_db.SaveChanges();
}

Related

WebAPI Controller GetAll or Get some Id

I have a controller like this
[Route("api/Foo/MyController/{id}")]
public IHttpActionResult Get(int id)
{
//Code code
foo(id); // Foo accept Int or Null
}
This do work, if call api/Foo/MyController/1, but i needed call api/Foo/MyController like it "GetAll" the parameter id now is null and the stuff into controller return all, how go there?
You can add a new method and route:
[Route("api/Foo/MyController")]
public IHttpActionResult Get()
{
//Code code
}
Edit: to reuse the same method you could use optional parameters:
[Route("api/Foo/MyController/{id}")]
public IHttpActionResult Get(int? id)
{
if (id.HasValue)
{
// get by id
}
else
{
// get all
}
}
Why don't have 2 separate methods:
[Route("api/Foo/")]
public IHttpActionResult GetAll()
{
// code
}
[Route("api/Foo/{id}")]
public IHttpActionResult GetById(int id)
{
// code
}
For clarity (readability, maintainability, supportability).
You could do also a optional parameter:
[Route("api/Foo/MyController/{id}")]
public IHttpActionResult Get(int? id = null)
{
IQueryable foo = GetData();
if (id.HasValue)
{
foo = foo.Where(e => e.Id == id.Value);
}
//...
}

it was not found in the ObjectStateManager

I have this code for deleted data from MSSQL database.
[HttpPost]
public ActionResult DeleteData(PartnerStudy partner)
{
var partnerStudy = GetByID(partner.Idetity);
DomainRepository repository = new DomainRepository();
repository.Delete(partnerStudy);
repository.SaveChanges();
return RedirectToAction("ShowData");
}
public PartnerStudy GetByID(int id)
{
DomainRepository repository = new DomainRepository();
//PartnerStudy partner = repository.GetItem<PartnerStudy>(id);
var partner = repository.GetItem<PartnerStudy>(id);
repository.Dispose();
return partner;
}
In DomainRepository have this
public void Delete<T>(T item) where T : class, IEntity
{
Set<T>().Remove(item);
}
here I have a problem.
If I try to delete have a error in line Set<T>().Remove(item);
{"The object cannot be deleted because it was not found in the
ObjectStateManager."}
What does mean ?
Why not found and where is ObjectStateManager ?
Thanks for answers!
You need to send the repository variable as a parameter to the GetByID() method, and use the same repository for getting and deleting the item.
[HttpPost]
public ActionResult DeleteData(PartnerStudy partner)
{
using(var repository = new DomainRepository())
{
var partnerStudy = GetByID(partner.Idetity, repository);
repository.Delete(partnerStudy);
repository.SaveChanges();
}
return RedirectToAction("ShowData");
}
private PartnerStudy GetByID(int id, DomainRepository repository)
{
var partner = repository.GetItem<PartnerStudy>(id);
return partner;
}
I even added a using block, as it seems DomainRepository implements IDisposable.

How Many Delete or Put methods in a WebApi Controller?

I have a problem with ASP.NET WebAPI`. I wanted to keep in RESTful API, so I create some apis in one controller, such as:
GET /api/user/ - userslist
GET /api/user/{id} - a user
GET /api/user/{id}/books - get all books of the user
Delete /api/user/{id} - delete the user
Delete /api/user/{id}/books - delete users' books
All the Get methods works fine, but only one Delete method can work, when the other was called, it will got a 405 response. Could you help me ?
Thanks. here is my controller
[RoutePrefix("api/Car")]//AttributeRouting asp.net 4.0 (not 5.0)
public class CarController : ApiController
{
public CarInfoPagedList GetCarInfos(int page = 0, int limit = 10)
{
var list = new CarInfoPagedList();
return list;
}
[HttpRoute("{id}")]
public string GetCarById(string id, string time = " ")
{
return "some";
}
[HttpRoute("{id}/runtime")]
public CarState GetCarRuntime(string id) {
return new CarState(id);
}
[DELETE("{id}")]//405
public void DeleteCar(string id)
{
//TODO:remove car
}
[DELETE("{id}/terminal/{terminalId}")]//work fine
public void Delete(string id, string terminalId)
{
}
[PUT("{id}/")]//405
public void PutCar(string id, CarInfo car)
{
}
[PUT("{id}/terminal/{terminalId}")]//work fine
public void Put(string id, string terminalID)
{
}
}

Multiple Get actions with different attribute routing?

If I design my controller in such a way:
public class ItemController : ApiController
{
[HttpGet]
[RoutePrefix("item/dosomething")]
public void DoSomething(Item item)
{ }
[HttpGet]
[RoutePrefix("item/dosomethingnicer")]
public void DoSomethingNicer(Item item)
{ }
[HttpGet]
[RoutePrefix("item/dosomethingelse")]
public void DoSomethingElse(Item item)
{ }
}
Would this work?
I would expect a structure more akin to this:
[RoutePrefix("item")]
public class ItemController : ApiController
{
[HttpGet]
[Route("dosomething")]
public void DoSomething(Item item)
{ }
[HttpGet]
[Route("dosomethingnicer")]
public void DoSomethingNicer(Item item)
{ }
[HttpGet]
[Route("dosomethingelse")]
public void DoSomethingElse(Item item)
{ }
}
I use Web Api 2 in this way in a lot of Controllers:
[HttpGet]
[Route("~/api/{version}/research/export")]
public IHttpActionResult Export(){
do stuff...
}
[HttpPost]
[Route("~/api/{version}/research/list")]
public IHttpActionResult List()
{
do stuff...
}
I use full api path description and it works with no problems.

Changes made to an entity in MVC are not being commited to the database

I am using Repository Pattern and Entity Framework to communicate with my database and Core stuff.
When I try to make a change to a user entity (change email address, username etc), it does not commit this change in the database. I realise I have missed some stuff out of the update method in my repositoy base, the trouble I am having is finding what I have missed out. Any ideas what I am missing? Very new to repository pattern.
I have been following the tutorial - https://workspaces.codeproject.com/user-10620241/architecture-guide-asp-net-mvc-framework-n-tier-en
MVC Controller
public ActionResult Details(int id = 0)
{
UserModel user = _userService.GetSingle(u => u.Id == id);
if (user == null)
{
return HttpNotFound();
}
return View(user);
}
[HttpPost]
public ActionResult Details(UserModel model)
{
if (ModelState.IsValid)
{
_userService.Update(model);
return RedirectToAction("Index");
}
return View(model);
}
RepositoryBase.cs
public abstract class RepositoryBase<T> : IRepository<T>
where T: class
{
public RepositoryBase()
: this(new ObRepositoryContext())
{
}
public RepositoryBase(IRepositoryContext repositoryContext)
{
repositoryContext = repositoryContext ?? new ObRepositoryContext();
_objectSet = repositoryContext.GetObjectSet<T>();
}
private IObjectSet<T> _objectSet;
public IObjectSet<T> ObjectSet
{
get
{
return _objectSet;
}
}
#region IRepository Members
public void Add(T entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
this.ObjectSet.AddObject(entity);
}
public void Update(T entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
this._objectSet.Attach(entity);
//TODO: Commit update to database here
}
public void Delete(T entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
this.ObjectSet.DeleteObject(entity);
}
public IList<T> GetAll()
{
return this.ObjectSet.ToList<T>();
}
public IList<T> GetAll(Expression<Func<T, bool>> whereCondition)
{
return this.ObjectSet.Where(whereCondition).ToList<T>();
}
public T GetSingle(Expression<Func<T, bool>> whereCondition)
{
return this.ObjectSet.Where(whereCondition).FirstOrDefault<T>();
}
public void Attach(T entity)
{
this.ObjectSet.Attach(entity);
}
public IQueryable<T> GetQueryable()
{
return this.ObjectSet.AsQueryable<T>();
}
public long Count()
{
return this.ObjectSet.LongCount<T>();
}
public long Count(Expression<Func<T, bool>> whereCondition)
{
return this.ObjectSet.Where(whereCondition).LongCount<T>();
}
#endregion
}
Well, you seem to have left yourself a TODO :)
//TODO: Commit update to database here
You'll need to flag the object as Modified - here's a take at this:
this.ObjectSet.Context.ObjectStateManager.ChangeObjectState(
entity, EntityState.Modified);
You are also going to want to call SaveChanges at some point on your context - it seems the pattern you have encourages multiple changes and one final commit at some point:
repositoryContext.SaveChanges();
Edit
The compile error is because the repo you are using has abstracted ObjectSet to its interface, IObjectSet. You'll need to downcast it again:
_objectSet // Or I guess (this.ObjectSet as ObjectSet<T>)
.Context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
Note that the pattern you are following was done in 2010 with EF 4.0. A lot has happened with Entity Framework since then, most notably DBContext which closes much of the gap with the repository pattern, IMO.

Categories