I am an experienced programmer but relatively new to c# mvc. I am attempting to create my first viewmodel to combine two models into one so a view can access members from both. I have followed instructions on combining distinct models into one view model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ViApplication.Models;
using System.ComponentModel.DataAnnotations;
namespace ViApplication.ViewModel
{
public class TemplateMTMQuestionViewModel
{
public TemplateVISpdat ThisTemplate { get; set; }
public MtmTemplateViSpdatQuestion ThisMTMQuestion { get; set; }
}
}
I have created a controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ViApplication.ViewModel;
using ViApplication.Models;
using System.Net;
namespace ViApplication.Controllers
{
public class TemplatesMTMQuestions : Controller
{
private VulnerabilityIndexDatabaseEntities db = new VulnerabilityIndexDatabaseEntities();
public ActionResult AddQuestionToTemplate(long? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
TemplateVISpdat templateVISpdat = GetTemplateByID(id);
if (templateVISpdat == null)
{
return HttpNotFound();
}
TemplateMTMQuestionViewModel TMTMQVM = new TemplateMTMQuestionViewModel();
TMTMQVM.ThisTemplate = GetTemplateByID(id);
TMTMQVM.ThisMTMQuestion = GetBlankMtmTemplateViSpdatQuestion();
return View(TMTMQVM);
}
public TemplateVISpdat GetTemplateByID(long? id)
{
TemplateVISpdat templateVISpdat = db.TemplateVISpdats.Find(id);
return templateVISpdat;
}
public MtmTemplateViSpdatQuestion GetBlankMtmTemplateViSpdatQuestion()
{
MtmTemplateViSpdatQuestion TMTMQVM = new MtmTemplateViSpdatQuestion();
return TMTMQVM;
}
}
}
This compiles fine. But when I try to create a view from AddQuestionToTemplate and select Empty and my ViewModel I get:
Unable to retrieve metadata for
ViApplication.ViewMdoel.TemplateMTMQuestionViewModel. One or more
validation errors were detected during model generation.
TemplateMTMQuestionViewModel::EntityType TemplateMTMQuestionViewModel
has no key defined
The only difference between this project and other projects is that I am using database first.
Any help would be greatly appreciated.
Related
Have spent way too much time trying to figure this out. Thanks for any help. .Net Core 3.1 trying to register a service in Startup.cs
Error CS0311: The type 'Apex.UI.MVC.ProjectService' cannot be used as type parameter 'TImplementation' in the generic type or method ServiceCollectionServiceExtensions.AddScoped<TService, TImplementation>(IServiceCollection). There is no implicit reference conversion from 'Apex.UI.MVC.ProjectService' to 'Apex.EF.Data.IProjects'. (CS0311) (Apex.UI.MVC)
services.AddScoped<IProjects, ProjectService>();
using System;
using Apex.EF.Data;
using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;
using System.Linq;
using Apex.UI.MVC.Models.Projects;
namespace Apex.UI.MVC.Controllers
{
public class ProjectController : Controller
{
private IProjects _projects;
public ProjectController(IProjects projects)
{
_projects = projects;
}
public IActionResult Index()
{
var projectModels = _projects.GetAll();
var listingResult = projectModels
.Select(result => new ProjectIndexListingModel
{
Id = result.Id,
ProjectName = result.ProjectName,
ProjectImage = result.ProjectImage
});
var model = new ProjectIndexModel()
{
Project = listingResult
};
return View(model);
}
}
}
using System;
using System.Collections.Generic;
using Apex.EF.Data;
using Apex.EF.Data.Models;
namespace Apex.EF.Data
{
public interface IProjects
{
IEnumerable<Project> GetAll();
Project GetById(int id);
void Add(Project newProject);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using Apex.EF.Data;
using Apex.EF.Data.Models;
using Microsoft.EntityFrameworkCore;
namespace ApexServices
{
public class ProjectService : IProjects
{
private ApexContext _context;
public ProjectService(ApexContext context)
{
_context = context;
}
public void Add(Project newProject)
{
_context.Add(newProject);
_context.SaveChanges();
}
public IEnumerable<Project> GetAll()
{
return _context.Projects
.Include(project => project.Status.IsInShop == true);
}
public Project GetById(int id)
{
return _context.Projects
.Include(project => project.Status.IsInShop==true)
.FirstOrDefault(project => project.Id == id);
}
}
}
The namespaces shown in the exception are different to the example code shown. There are probably conflicting types in the project (not shown).
If that is really the case, then include the full namespace when registering the type with the container to avoid conflicts.
Based on the shown code, that would be
services.AddScoped<IProjects, ApexServices.ProjectService>();
I want to update only one filed of the DB. I am creating a function in my Controller (AOProf Controller) that looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Accommodation_App.Models;
using System.Data.Entity;
namespace Accommodation_App.Controllers
{
public class AOProfController : Controller
{
private StudAccommodationEntities1 SContextUser;
private DbSet<User> UserDb;
private StudAccommodationEntities1Entities SContextProp;
private DbSet<Property> Properties;
public AOProfController()
{
SContextUser = new StudAccommodationEntities1();
UserDb = SContextUser.UserDb;
SContextProp = new StudAccommodationEntities1Entities();
Properties = SContextProp.Properties;
}
[HttpPost]
public ActionResult Reject(int id)
{
Property obj = Properties.Find(id);
if (obj != null)
{
obj.isApproved = false;
UpdateModel(obj);
SContextProp.SaveChanges();
}
else{
return Content("Not such an object");
}
return Content("the rejected is confirmed");
}
And in my view I call this function from the onclick event. I sent the param before to the view. It is send correctly.
<button value="Reject" onclick="location.href='#Url.Action("Reject", "AOProf", new { id = item.ProId })'" >Reject</button>
The url that appears in the URL bar after clicking the button is
http://localhost:54464/AOProf/Reject/1
It looks fine, but the record won't update in the database. It will stay the same. Can you please, help me to understand how to to do it the right way?
I have the following:
public class StripeController : Controller
{
private readonly UserService _userService;
public StripeController(UserService userService)
{
_userService = userService;
}
[HttpPost]
public ActionResult StripeWebook()
{
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
[HttpPost]
[Route("api/stripewebhook")]
public async Task<ActionResult> Index(CancellationToken ct)
{
var json = new StreamReader(Request.InputStream).ReadToEnd();
var stripeEvent = StripeEventUtility.ParseEvent(json);
switch (stripeEvent.Type)
{
case StripeEvents.ChargeRefunded: // all of the types available are listed in StripeEvents
var stripeCharge = Stripe.Mapper<StripeCharge>.MapFromJson(stripeEvent.Data.Object.ToString());
break;
}
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
}
And requests from stripe generate an error:
The controller for path '/api/stripewebhook' was not found or does not implement IController
Any idea why this is happening when I test from the stripe portal?
Using WebApi 2 it works with no problem.
Here is the smallest WebApi controller to begin with:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
namespace WebApplication1.Controllers
{
public class StripeController : ApiController
{
[HttpPost]
[Route("api/stripewebhook")]
public IHttpActionResult Index()
{
var json = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd();
return Ok();
}
}
}
if you execute this from VS you can access it from http://localhost:(port)/api/stripewebhook
Now you only need to extend this to include the stripe code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
namespace WebApplication1.Controllers
{
public class StripeController : ApiController
{
[HttpPost]
[Route("api/stripewebhook")]
public IHttpActionResult Index()
{
var json = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd();
var stripeEvent = StripeEventUtility.ParseEvent(json);
switch (stripeEvent.Type)
{
case StripeEvents.ChargeRefunded: // all of the types available are listed in StripeEvents
var stripeCharge = Stripe.Mapper<StripeCharge>.MapFromJson(stripeEvent.Data.Object.ToString());
break;
}
return Ok();
}
}
}
I am trying to create a web api with forms based authentication. I want to login from a client and retrieve data from there. When I log in, user gets authenticated and can retrieve data by giving http request direct into adressbar like localhost:1393/api/Game. But when i try to get it from client I am getting a 401 (Unauthorized error). I have enabled CORS in server side. This is the controller to handle data
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Web.Security;
using Cheeky_backend.Models;
using System.Web.Http.WebHost;
namespace Cheeky_backend.Controllers
{
public class Demo
{
public List<Teams> team { get; set; }
public List<Hole> hole { get; set; }
}
[Authorize]
public class GameController : ApiController
{
private Cheeky_backendContext db = new Cheeky_backendContext();
// GET api/Game
public IEnumerable<Hole> GetHoles()
{
return db.Holes.AsEnumerable();
}
}
}
This is the authenticating controler
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Security;
using System.Web.Http;
using Cheeky_backend.Models;
namespace Cheeky_backend.Controllers
{
public class UserController : ApiController
{
private Cheeky_backendContext db = new Cheeky_backendContext();
// GET api/Default1
// GET api/Default1/5
// PUT api/Default1/5
// POST api/Default1
public HttpResponseMessage CreateUser(User user)
{
if (ModelState.IsValid)
{
db.Users.Add(user);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, user);
// response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = user.ID }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
// DELETE api/Default1/5
public HttpResponseMessage Login(User user)
{
var userfound = from user2 in db.Users
where user.username == user2.username && user.password == user2.password
select user2;
if( userfound.Any())
{
FormsAuthentication.SetAuthCookie(user.username, true);
return Request.CreateResponse(HttpStatusCode.OK,user);
}
return Request.CreateResponse(HttpStatusCode.Unauthorized);
}
}
}
Source
In your Authentication Handler
Don't set the Principal on the Thread.CurrentPrinicipal any more.
Use the Principal on the HttpRequestContext.
Take a look at here
I'm trying to link my MVC project with a database using Entity Framework, but I can't figure out how to store new records to a database. So far I have the following code:
//model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using MvcApplication1.Controllers;
namespace MvcApplication1.Models
{
public class CarUser
{
public int ID { get; set; }
[DisplayName ("First Name")]
public string Fname { get; set; }
[DisplayName ("Surname")]
public string Sname { get; set; }
}
}
//controller
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public class CarUserController : Controller
{
private FormDataContext db = new FormDataContext();
//
// GET: /CarUser/
public ActionResult Index()
{
return View(db.CarUsers.ToList());
}
//
// GET: /CarUser/Details/5
public ActionResult Details(int id = 0)
{
CarUser caruser = db.CarUsers.Find(id);
if (caruser == null)
{
return HttpNotFound();
}
return View(caruser);
}
//
// GET: /CarUser/Create
public ActionResult Create()
{
return View();
}
//
// POST: /CarUser/Create
[HttpPost]
public ActionResult Create(CarUser caruser)
{
if (ModelState.IsValid)
{
db.CarUsers.Add(caruser);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(caruser);
}
//
// GET: /CarUser/Edit/5
public ActionResult Edit(int id = 0)
{
CarUser caruser = db.CarUsers.Find(id);
if (caruser == null)
{
return HttpNotFound();
}
return View(caruser);
}
//
// POST: /CarUser/Edit/5
[HttpPost]
public ActionResult Edit(CarUser caruser)
{
if (ModelState.IsValid)
{
db.Entry(caruser).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(caruser);
}
//
// GET: /CarUser/Delete/5
public ActionResult Delete(int id = 0)
{
CarUser caruser = db.CarUsers.Find(id);
if (caruser == null)
{
return HttpNotFound();
}
return View(caruser);
}
//
// POST: /CarUser/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
CarUser caruser = db.CarUsers.Find(id);
db.CarUsers.Remove(caruser);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
//formdatacontext
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
namespace MvcApplication1.Models
{
public class FormDataContext : DbContext
{
public DbSet<CarUser> CarUsers
{ get; set; }
}
}
//formdatainitialiser
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.IO;
namespace MvcApplication1.Models
{
public class FormDataInitializer : DropCreateDatabaseAlways<FormDataContext>
{
protected override void Seed(FormDataContext context)
{
base.Seed(context);
var CarUsers = new List<CarUser>
{
new CarUser {
ID = 1,
Fname = "Craig",
Sname = "Higginson",
}
};
CarUsers.ForEach(s => context.CarUsers.Add(s));
context.SaveChanges();
}
}
}
I've also got the following in my web.config file
<connectionStrings>
<add name="FormDataContext"
connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=FormData.mdf;Integrated Security=True" providerName="System.Data.SqlClient" />
This all builds fine, and when I navigate to /caruser i am able to create new records. These records aren't being stored in my database.
Do I need to create the table in the database first or should Entity Framework create this for me, if i have referenced the database correctly?
If you're using a Code First approach then Entity Framework will build the table for you. It looks like you are not using Code First, so you will have create the table in the database. I assume you're using an Entity Data Model (.edmx)? If so, you will create your table in the database, then update your data model (.edmx). If you have not yet created your .edmx file, you need to do that - the .edmx file will contain all your CRUD operations.
What I'm confused about is I'd imagine your code would throw an error if the table did not exist (i.e. if the table represented by your data model didn't map to an actual table in the database, because it doesn't exist). So, the question is, does your table already exist? If it does, then step through the code line by line to find out why your records aren't being saved. If it doesn't exist, then add the table via SQL Server Management Studio (or similar), then open your .edmx file, right click on the layout that comes up, click "Update Model from database".
You can find all needed info here:
creating-an-entity-framework-data-model-for-an-asp-net-mvc-application
First you have add an edmx project to your existing solution which is a mockup of db and contains all the tables and SPs.
From your action method make a call to one more class, say DataAccessLayer.cs.
In DataAccessLayer.cs, add a reference to your edmx project.
Use this code:
using (var entity = new FormDataContext())
{
//entity. will give you all the tables in the database.
}