So, i have two projects, WebAPI and Client. The Client uses the database of the WebAPI project, and does not have it's own. Everything is working fine in one-to-one relationships and one-to-many relationships. However, i now need to figure out how to make it work with many-to-many relationships. I'll be posting my code, so, to better explain myself i will write with the real class names as you will be able to understand due to the code i will post further.
In my WebApi.Models i have two classes, PlanoManutencao and Ativo. This is a many-to-many relationship. Here are the classes:
public class PlanoManutencao
{
public PlanoManutencao()
{
Ativos = new List<Ativo>();
Operacoes = new List<Operacao>();
}
public int ID { get; set; }
public string Nome { get; set; }
public string Observacoes { get; set; }
public bool Permanente { get; set; }
public DateTime DataCriacao { get; set; }
public virtual ICollection<Ativo> Ativos { get; set; }
public virtual ICollection<Operacao> Operacoes { get; set; }
}
public class Ativo
{
public Ativo()
{
PlanosManutencao = new List<PlanoManutencao>();
}
public int ID { get; set; }
public string Nome { get; set; }
public string Descricao { get; set; }
public virtual ICollection<PlanoManutencao> PlanosManutencao { get; set; }
}
Now, in my WebAPI i'm using repositories, as follows:
public class PlanosManutencaoRepository : IPlanosManutencaoRepository
{
public ApplicationDbContext context;
public PlanosManutencaoRepository()
{
context = new ApplicationDbContext();
}
public PlanoManutencao Create(PlanoManutencao planoManutencao)
{
context.PlanosManutencao.Add(planoManutencao);
context.SaveChanges();
return planoManutencao;
}
public bool Delete(int id)
{
var planoManutencao = context.PlanosManutencao.Find(id);
if (planoManutencao != null)
{
context.PlanosManutencao.Remove(planoManutencao);
context.SaveChanges();
return true;
}
else return false;
}
public List<PlanoManutencao> GetData()
{
var planosManutencao = context.PlanosManutencao.ToList();
return planosManutencao;
}
public List<PlanoManutencao> GetData(DateTime data)
{
var planosManutencao = context.PlanosManutencao.Where(f => f.DataCriacao == data);
return planosManutencao.ToList();
}
public PlanoManutencao GetDataById(int id)
{
return context.PlanosManutencao.Find(id);
}
public bool Update(int id, PlanoManutencao planoManutencao)
{
var planoManutencaoAux = context.PlanosManutencao.Find(id);
if (planoManutencao != null)
{
planoManutencaoAux.DataCriacao = planoManutencao.DataCriacao;
context.SaveChanges();
return true;
}
else return false;
}
}
public class AtivosRepository : IAtivosRepository
{
public ApplicationDbContext context;
public AtivosRepository()
{
context = new ApplicationDbContext();
}
public Ativo Create(Ativo ativo)
{
context.Ativos.Add(ativo);
context.SaveChanges();
return ativo;
}
public bool Delete(int id)
{
var ativo = context.Ativos.Find(id);
if (ativo != null)
{
context.Ativos.Remove(ativo);
context.SaveChanges();
return true;
}
else return false;
}
public List<Ativo> GetData()
{
var ativos = context.Ativos.ToList();
return ativos;
}
public List<Ativo> GetData(string descricao)
{
var ativos = context.Ativos.Where(f => f.Descricao == descricao);
return ativos.ToList();
}
public Ativo GetDataById(int id)
{
return context.Ativos.Find(id);
}
public bool Update(int id, Ativo ativo)
{
var ativoAux = context.Ativos.Find(id);
if (ativo != null)
{
ativoAux.Nome = ativo.Nome;
ativoAux.Descricao = ativo.Descricao;
context.SaveChanges();
return true;
}
else return false;
}
}
Now, for the controllers, i have:
public class PlanosManutencaoController : ApiController
{
//private ApplicationDbContext db = new ApplicationDbContext();
private IPlanosManutencaoRepository repoPM = new PlanosManutencaoRepository();
// GET: api/PlanosManutencao
public IQueryable<PlanoManutencao> GetPlanoManutencaos()
{
return repoPM.GetData().AsQueryable();
}
// GET: api/PlanosManutencao/5
[ResponseType(typeof(PlanoManutencao))]
public IHttpActionResult GetPlanoManutencao(int id)
{
PlanoManutencao planoManutencao = repoPM.GetDataById(id);
if (planoManutencao == null)
{
return NotFound();
}
return Ok(planoManutencao);
}
// PUT: api/PlanosManutencao/5
[ResponseType(typeof(void))]
public IHttpActionResult PutPlanoManutencao(int id, PlanoManutencao planoManutencao)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != planoManutencao.ID)
{
return BadRequest();
}
bool isSucess = repoPM.Update(id, planoManutencao);
if (!PlanoManutencaoExists(id))
{
return NotFound();
}
return Ok();
}
// POST: api/PlanosManutencao
[ResponseType(typeof(PlanoManutencao))]
public IHttpActionResult PostPlanoManutencao(PlanoManutencao planoManutencao)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (repoPM.Create(planoManutencao) == null)
{
return StatusCode(HttpStatusCode.BadRequest);
}
return CreatedAtRoute("DefaultApi", new { id = planoManutencao.ID }, planoManutencao);
}
// DELETE: api/PlanosManutencao/5
[ResponseType(typeof(PlanoManutencao))]
public IHttpActionResult DeletePlanoManutencao(int id)
{
PlanoManutencao planoManutencao = repoPM.GetDataById(id);
if (planoManutencao == null)
{
return NotFound();
}
bool isSuccess = repoPM.Delete(id);
if (!isSuccess)
{
return StatusCode(HttpStatusCode.BadRequest);
}
return Ok();
}
private bool PlanoManutencaoExists(int id)
{
return repoPM.GetDataById(id) == null ? false : true;
}
}
public class AtivosController : ApiController
{
//private ApplicationDbContext db = new ApplicationDbContext();
private IAtivosRepository repoA = new AtivosRepository();
// GET: api/Ativos
public IQueryable<Ativo> GetAtivoes()
{
return repoA.GetData().AsQueryable();
}
// GET: api/Ativos/5
[ResponseType(typeof(Ativo))]
public IHttpActionResult GetAtivo(int id)
{
Ativo ativo = repoA.GetDataById(id);
if (ativo == null)
{
return NotFound();
}
return Ok(ativo);
}
// PUT: api/Ativos/5
[ResponseType(typeof(void))]
public IHttpActionResult PutAtivo(int id, Ativo ativo)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != ativo.ID)
{
return BadRequest();
}
bool isSucess = repoA.Update(id, ativo);
if (!AtivoExists(id))
{
return NotFound();
}
return Ok();
}
// POST: api/Ativos
[ResponseType(typeof(Ativo))]
public IHttpActionResult PostAtivo(Ativo ativo)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (repoA.Create(ativo) == null)
{
return StatusCode(HttpStatusCode.BadRequest);
}
return CreatedAtRoute("DefaultApi", new { id = ativo.ID }, ativo);
}
// DELETE: api/Ativos/5
[ResponseType(typeof(Ativo))]
public IHttpActionResult DeleteAtivo(int id)
{
Ativo ativo = repoA.GetDataById(id);
if (ativo == null)
{
return NotFound();
}
bool isSuccess = repoA.Delete(id);
if (!isSuccess)
{
return StatusCode(HttpStatusCode.BadRequest);
}
return Ok();
}
private bool AtivoExists(int id)
{
return repoA.GetDataById(id) == null ? false : true;
}
}
Now, as for the Client project, i'm using ViewModels,Controllers and Views. ViewModels:
public class PlanoManutencaoViewModel
{
public PlanoManutencaoViewModel()
{
Ativos = new List<AtivoViewModel>();
Operacoes = new List<OperacaoViewModel>();
}
public int ID { get; set; }
[Display(Name = "Name")]
public string Nome { get; set; }
[Display(Name = "Observations")]
public string Observacoes { get; set; }
[Display(Name = "Permanent")]
public bool Permanente { get; set; }
[Display(Name = "Created")]
public DateTime DataCriacao { get; set; }
[Display(Name = "Assets")]
public virtual ICollection<AtivoViewModel> Ativos { get; set; }
[Display(Name = "Tasks")]
public virtual ICollection<OperacaoViewModel> Operacoes { get; set; }
}
public class AtivoViewModel
{
public AtivoViewModel()
{
PlanosManutencao = new List<PlanoManutencaoViewModel>();
}
public int ID { get; set; }
[Display(Name = "Name")]
public string Nome { get; set; }
[Display(Name = "Description")]
public string Descricao { get; set; }
public ICollection<PlanoManutencaoViewModel> PlanosManutencao { get; set; }
}
The controllers are as follows:
public class PlanosManutencaoController : Controller
{
// GET: PlanosManutencao
public async Task<ActionResult> Index()
{
var client = WebApiHttpClient.GetClient();
HttpResponseMessage response = await client.GetAsync("api/PlanosManutencao");
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
var planosManutencao =
JsonConvert.DeserializeObject<IEnumerable<PlanoManutencaoViewModel>>(content);
return View(planosManutencao);
}
else
{
return Content("Ocorreu um erro: " + response.StatusCode);
}
}
// GET: PlanosManutencao/Details/5
public async Task<ActionResult> Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var client = WebApiHttpClient.GetClient();
HttpResponseMessage response = await client.GetAsync("api/PlanosManutencao/" + id);
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
var plano = JsonConvert.DeserializeObject<PlanoManutencaoViewModel>(content);
if (plano == null) return HttpNotFound();
return View(plano);
}
else
{
return Content("Ocorreu um erro: " + response.StatusCode);
}
}
// GET: PlanosManutencao/Create
public ActionResult Create()
{
PopulateDropDownListForAtivos();
return View();
}
// POST: PlanosManutencao/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(PlanoManutencaoViewModel planoManutencao)
{
try
{
PopulateDropDownListForAtivos(planoManutencao.Ativos);
var client = WebApiHttpClient.GetClient();
string planoManutencaoJSON = JsonConvert.SerializeObject(planoManutencao);
HttpContent content = new StringContent(planoManutencaoJSON, System.Text.Encoding.Unicode, "application/json");
var response = await client.PostAsync("api/PlanosManutencao", content);
if (response.IsSuccessStatusCode)
{
return RedirectToAction("Index");
}
else
{
return Content("Ocorreu um erro: " + response.StatusCode);
}
}
catch
{
return Content("Ocorreu um erro.");
}
}
// GET: PlanosManutencao/Edit/5
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var client = WebApiHttpClient.GetClient();
HttpResponseMessage response = await client.GetAsync("api/PlanosManutencao/" + id);
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
var planoManutencao = JsonConvert.DeserializeObject<PlanoManutencaoViewModel>(content);
if (planoManutencao == null) return HttpNotFound();
return View(planoManutencao);
}
return Content("Ocorreu um erro: " + response.StatusCode);
}
// POST: PlanosManutencao/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(PlanoManutencaoViewModel planoManutencao)
{
try
{
var client = WebApiHttpClient.GetClient();
string planoManutencaoJSON = JsonConvert.SerializeObject(planoManutencao);
HttpContent content = new StringContent(planoManutencaoJSON, System.Text.Encoding.Unicode, "application/json");
var response =
await client.PutAsync("api/PlanosManutencao/" + planoManutencao.ID, content);
if (response.IsSuccessStatusCode)
{
return RedirectToAction("Index");
}
else
{
return Content("Ocorreu um erro: " + response.StatusCode);
}
}
catch
{
return Content("Ocorreu um erro.");
}
}
// GET: PlanosManutencao/Delete/5
public async Task<ActionResult> Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var client = WebApiHttpClient.GetClient();
HttpResponseMessage response = await client.GetAsync("api/PlanosManutencao/" + id);
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
var planoManutencao = JsonConvert.DeserializeObject<PlanoManutencaoViewModel>(content);
if (planoManutencao == null) return HttpNotFound();
return View(planoManutencao);
}
return Content("Ocorreu um erro: " + response.StatusCode);
}
// POST: PlanosManutencao/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> DeleteConfirmed(int id)
{
try
{
var client = WebApiHttpClient.GetClient();
var response = await client.DeleteAsync("api/PlanosManutencao/" + id);
if (response.IsSuccessStatusCode)
{
return RedirectToAction("Index");
}
else
{
return Content("Ocorreu um erro: " + response.StatusCode);
}
}
catch
{
return Content("Ocorreu um erro.");
}
}
private void PopulateDropDownListForAtivos(object ativos = null)
{
IEnumerable<AtivoViewModel> vm = null;
using (var client=WebApiHttpClient.GetClient())
{
HttpResponseMessage response = client.GetAsync("api/Ativos").Result;
if(response.IsSuccessStatusCode)
{
vm = response.Content.ReadAsAsync<IEnumerable<AtivoViewModel>>().Result;
}
}
var Ativos = vm.ToList().OrderBy(i => i.ID);
ViewBag.Ativos = new SelectList(Ativos, "ID", "Nome");
}
}
public class AtivosController : Controller
{
// GET: Ativos
public async Task<ActionResult> Index()
{
var client = WebApiHttpClient.GetClient();
HttpResponseMessage response = await client.GetAsync("api/Ativos");
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
var ativos =
JsonConvert.DeserializeObject<IEnumerable<AtivoViewModel>>(content);
return View(ativos);
}
else
{
return Content("Ocorreu um erro: " + response.StatusCode);
}
}
// GET: Ativos/Details/5
public async Task<ActionResult> Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var client = WebApiHttpClient.GetClient();
HttpResponseMessage response = await client.GetAsync("api/Ativos/" + id);
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
var ativo = JsonConvert.DeserializeObject<AtivoViewModel>(content);
if (ativo == null) return HttpNotFound();
return View(ativo);
}
else
{
return Content("Ocorreu um erro: " + response.StatusCode);
}
}
// GET: Ativos/Create
public ActionResult Create()
{
return View();
}
// POST: Ativos/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(AtivoViewModel ativo)
{
try
{
var client = WebApiHttpClient.GetClient();
string ativoJSON = JsonConvert.SerializeObject(ativo);
HttpContent content = new StringContent(ativoJSON, System.Text.Encoding.Unicode, "application/json");
var response = await client.PostAsync("api/Ativos", content);
if (response.IsSuccessStatusCode)
{
return RedirectToAction("Index");
}
else
{
return Content("Ocorreu um erro: " + response.StatusCode);
}
}
catch
{
return Content("Ocorreu um erro.");
}
}
// GET: Ativos/Edit/5
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var client = WebApiHttpClient.GetClient();
HttpResponseMessage response = await client.GetAsync("api/Ativos/" + id);
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
var ativo = JsonConvert.DeserializeObject<AtivoViewModel>(content);
if (ativo == null) return HttpNotFound();
return View(ativo);
}
return Content("Ocorreu um erro: " + response.StatusCode);
}
// POST: Ativos/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(AtivoViewModel ativo)
{
try
{
var client = WebApiHttpClient.GetClient();
string ativoJSON = JsonConvert.SerializeObject(ativo);
HttpContent content = new StringContent(ativoJSON, System.Text.Encoding.Unicode, "application/json");
var response =
await client.PutAsync("api/Ativos/" + ativo.ID, content);
if (response.IsSuccessStatusCode)
{
return RedirectToAction("Index");
}
else
{
return Content("Ocorreu um erro: " + response.StatusCode);
}
}
catch
{
return Content("Ocorreu um erro.");
}
}
// GET: Ativos/Delete/5
public async Task<ActionResult> Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var client = WebApiHttpClient.GetClient();
HttpResponseMessage response = await client.GetAsync("api/Ativos/" + id);
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
var ativo = JsonConvert.DeserializeObject<AtivoViewModel>(content);
if (ativo == null) return HttpNotFound();
return View(ativo);
}
return Content("Ocorreu um erro: " + response.StatusCode);
}
// POST: Ativos/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> DeleteConfirmed(int id)
{
try
{
var client = WebApiHttpClient.GetClient();
var response = await client.DeleteAsync("api/Ativos/" + id);
if (response.IsSuccessStatusCode)
{
return RedirectToAction("Index");
}
else
{
return Content("Ocorreu um erro: " + response.StatusCode);
}
}
catch
{
return Content("Ocorreu um erro.");
}
}
}
I'll post only the Create view of PlanoManutencao, which is:
<div class="form-horizontal">
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Nome, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Nome, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Nome, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Observacoes, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Observacoes, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Observacoes, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Permanente, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.Permanente)
@Html.ValidationMessageFor(model => model.Permanente, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="ativos">Assets</label>
<div class="col-md-10">
@Html.DropDownList("ativos",String.Empty)
@Html.ValidationMessageFor(model => model.Ativos)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.DataCriacao, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.DataCriacao, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.DataCriacao, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
EntityFramework creates the join table in the WebAPI DB just fine, but when i create one PlanoManutencao with one Ativo it creates the PlanoManutencao but does not add anything to the join table. I reckon it my be a mistake i have in the repositories or controllers, but i cannot solve it. I also followed lots of tutorials, none of which seem to solve my problem. I'm sorry for the long explanation, and thank you in advance, only for reading such a text :)
Try doing this inside your PlanosManutencaoRepo
:
public class PlanosManutencaoRepository : IPlanosManutencaoRepository
{
public PlanoManutencao Create(PlanoManutencao planoManutencao)
{
foreach(var a in planoManutencao.Ativos)
{
context.Ativos.Attach(a);
}
context.PlanosManutencao.Add(planoManutencao);
context.SaveChanges();
return planoManutencao;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.