I am new to MVC5 and i am trying to work on 'search' functionality. my aim is get data from a dataservice.(that is, i enter data into a form and hit the search button, if theres a record it displays data).
I have created a dependency to mock the data(dummy data). How do i wire up my code to the contoller to achieve my purpose?. Please advice Thank you.
Heres my controller and my mock:
public class SearchController : Controller
{
private readonly ISearchResultsService _resultsService;
public SearchController() : this(DependencyFactory.NewResultsService())
{
}
public SearchController(ISearchResultsService resultsService)
{
_resultsService = resultsService;
}
// GET:Search
public ActionResult Index()
{
return View();
}
// GET: Search/Details/5
public ActionResult Details(int id)
{
return View();
}
// GET: Search/Create
public ActionResult Create()
{
return View();
}
// POST: Search/Create
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
// TODO: Add insert logic here
return();
}
catch
{
return View();
}
}
//[HttpPost]
//public ActionResult Index(SearchCriteria data)
//{
// var data = this._resultsService.FindClaims(data);
// return View(data);
//}
[HttpPost]
public ActionResult Index()
{
return View();
}
// GET: Search/Edit/5
public ActionResult Edit(int id)
{
return View();
}
// POST: Search/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
// GET: Search/Delete/5
public ActionResult Delete(int id)
{
return View();
}
// POST: Search/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
try
{
// TODO: Add delete logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
public static class DependencyFactory
{
public static ISearchResultsService NewResultsService()
{
return new MockSearchResultsService();
}
}
public interface ISearchResultsService
{
List<Person> FindClaims(string firstName, string lastName);
}
public class MockSearchResultsService : ISearchResultsService
{
public List<Person> FindClaims(string firstName, string lastName)
{
return new List<Person>(new []{new Person{FirstName = "John", LastName = "Doe"}});//throw new NotImplementedException();
}
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
I recommend you to use some IoC container like http://autofac.org. You can configure your container and register your service like this way:
builder.RegisterType<MockSearchResultsService>().As<ISearchResultsService>()
All your dependencies will be automatically resolved:
public class SearchController : Controller
{
private readonly ISearchResultsService _resultsService;
public SearchController(ISearchResultsService resultsService)
{
_resultsService = resultsService;
}
}
Note that there is many IoC containers you can use. Try to search more about AutoFac, Ninject or Castle Windsor.
Related
As the question says I'm trying to figure out exactly how I would make it so when a user logs in they only see the data entries they have entered into the database. I used the ASP.NET Core Web App (Model-View_Controller) template to start.
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Power { get; set; }
public string Charges { get; set; }
public Item(){
}
}
This is the data in question, the items model. My initial thought was that I need a one to many relationship between the AspNetUsers table and the Items table and then change something in the items controller, but I'm not entirely sure how/if I can make edits to the AspNetUsers table.
public class ItemsController : Controller
{
private readonly ApplicationDbContext _context;
public ItemsController(ApplicationDbContext context)
{
_context = context;
}
// GET: Items
public async Task<IActionResult> Index()
{
//Return a list to the view
return View(await _context.Item.ToListAsync());
}
public async Task<IActionResult> SearchItems()
{
return View();
}
public async Task<IActionResult> ShowSearchResults(String SearchPhrase)
{
//Return a list from index where
return View("Index", await _context.Item.Where(j => j.Name.Contains(SearchPhrase)).ToListAsync());
}
// GET: Items/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var item = await _context.Item
.FirstOrDefaultAsync(m => m.Id == id);
if (item == null)
{
return NotFound();
}
return View(item);
}
// GET: Items/Create
[Authorize]
public IActionResult Create()
{
return View();
}
// POST: Items/Create
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Name,Description,Power,Charges")] Item item)
{
if (ModelState.IsValid)
{
_context.Add(item);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(item);
}
// GET: Items/Edit/5
[Authorize]
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var item = await _context.Item.FindAsync(id);
if (item == null)
{
return NotFound();
}
return View(item);
}
// POST: Items/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Name,Description,Power,Charges")] Item item)
{
if (id != item.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(item);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ItemExists(item.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(item);
}
// GET: Items/Delete/5
[Authorize]
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var item = await _context.Item
.FirstOrDefaultAsync(m => m.Id == id);
if (item == null)
{
return NotFound();
}
return View(item);
}
// POST: Items/Delete/5
[Authorize]
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var item = await _context.Item.FindAsync(id);
_context.Item.Remove(item);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool ItemExists(int id)
{
return _context.Item.Any(e => e.Id == id);
}
This is the items controller. If I need to give more information I can.
but I'm not entirely sure how/if I can make edits to the AspNetUsers table.
You can inherit from IdentityUser to custom user data.
Here is a working demo you could follow:
Model:
public class ApplicationUser:IdentityUser
{
public List<Item> Items { get; set; }
}
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Power { get; set; }
public string Charges { get; set; }
public ApplicationUser ApplicationUser { get; set; }
}
Controller:
public class ItemsController : Controller
{
private readonly ApplicationDbContext _context;
public ItemsController(ApplicationDbContext context)
{
_context = context;
}
// GET: Items
public async Task<IActionResult> Index()
{
var model = await _context.Item
.Where(a => a.ApplicationUser.Id == HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value)
.ToListAsync();
return View(model);
}
}
DbContext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Item> Item { get; set; }
}
Startup.cs:
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
Update Pages/Shared/_LoginPartial.cshtml and replace IdentityUser with ApplicationUser:
#using Microsoft.AspNetCore.Identity
#inject SignInManager<ApplicationUser> SignInManager
#inject UserManager<ApplicationUser> UserManager
Result:
I created a small website using ASP.NET MVC but it can not create new, edit or delete data from the database. The data only shows on the webpage but when i use SELECT * command in SQL the data is not shown.
My connection string in webconfig:
<add name="CodeFileDBContext"
providerName="System.Data.SqlClient"
connectionString="Data Source=HOANG-PC\SQLSERVER01;Initial Catalog=Ciaos;User Id=sa;Password=**********;MultipleActiveResultSets=True" />
Model:
namespace Ciao.Models
{
public class CodeFile
{
[Key]
public int ColdeFile_ID { get; set;}
public string Website_Name { get; set;}
public string Service_Name { get; set;}
public DateTime Date_In { get; set;}
public DateTime Date_Out { get; set;}
public int Service_Status { get; set;}
}
public class CodeFileDBContext : DbContext
{
public DbSet<CodeFile> tbl_CodeFile { get; set; }
}
}
Controller:
namespace Ciao.Controllers
{
public class CodeFileController : Controller
{
private CodeFileDBContext db = new CodeFileDBContext();
//
// GET: /CodeFile/
public ActionResult Index()
{
return View(db.tbl_CodeFile.ToList());
}
//
// GET: /CodeFile/Details/5
public ActionResult Details(int id = 0)
{
CodeFile codefile = db.tbl_CodeFile.Find(id);
if (codefile == null)
{
return HttpNotFound();
}
return View(codefile);
}
//
// GET: /CodeFile/Create
public ActionResult Create()
{
return View();
}
//
// POST: /CodeFile/Create
[HttpPost]
public ActionResult Create(CodeFile codefile)
{
if (ModelState.IsValid)
{
db.tbl_CodeFile.Add(codefile);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(codefile);
}
//
// GET: /CodeFile/Edit/5
public ActionResult Edit(int id = 0)
{
CodeFile codefile = db.tbl_CodeFile.Find(id);
if (codefile == null)
{
return HttpNotFound();
}
return View(codefile);
}
//
// POST: /CodeFile/Edit/5
[HttpPost]
public ActionResult Edit(CodeFile codefile)
{
if (ModelState.IsValid)
{
db.Entry(codefile).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(codefile);
}
//
// GET: /CodeFile/Delete/5
public ActionResult Delete(int id = 0)
{
CodeFile codefile = db.tbl_CodeFile.Find(id);
if (codefile == null)
{
return HttpNotFound();
}
return View(codefile);
}
//
// POST: /CodeFile/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
CodeFile codefile = db.tbl_CodeFile.Find(id);
db.tbl_CodeFile.Remove(codefile);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
Add constructor to your CodeFileDBContext class:
For example like this:
public CodeFileDBContext() : base("Name=CodeFileDBContext")
{
var adapter = (IObjectContextAdapter)this;
var objectContext = adapter.ObjectContext;
objectContext.CommandTimeout = 30; // value in seconds
}
DbContext base class accepts connectionstring name as parameter. Try passing the connection string name through CodeFileDBContext
Could you give us more details, what is the exact error you get?
Another thing you should check is that each data member in the model has its column in that specific table. If their names do not exactly match use the 'Column' attribute.
For instance, if they do not match try:
[Column("Table_Id")]
public int ID { get; set; }
If they all match, add the 'Table' attribute, it helped me many times before.
[Table("YourTableName")]
{
public class CodeFile....
}
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
//var clinicbusiness = new ClinicBusiness ();
return View();
}
[HttpPost]
public ActionResult ValidateCommand()
{
var pa = new PaymentView();
if (ModelState.IsValid)
return View("ValidateCommand");
else
return View();
}
public ActionResult RedirectFromPaypal()
{
return View("RedirectFromPaypal");
}
private ActionResult View(Func<ActionResult> RedirectFromPaypal)
{
throw new NotImplementedException();
}
this is my controller and i have a problem taking items from A CART
how to add cart items to a controller n accumulate price
using payfast checkout button
This is homework, an ASP.NET MVC app in Visual Studio using C#. When I run it, the error says, "Cannot implicitly convert type 'string' to 'int'," referring to the line: Manufacturer = collection["Manufacturer"], Gears = collection["Gears"], Frame = collection["Frame"] and there's a squiggly line under Gears = collection["Gears"].
using MvcApplication3.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcApplication3.Controllers
{
public class BikeController : Controller
{
//
// GET: /Bike/
List<Bike> bikes;
public BikeController()
{
if (bikes == null)
{
bikes = new List<Bike> {
new Bike(),
new Bike { Manufacturer = "Nishiki", Gears = 5, Frame = "Road" }
};
}
}
public ActionResult Index()
{
return View(this.bikes);
}
private ActionResult View(Func<object> func)
{
throw new NotImplementedException();
}
//
// GET: /Bike/Details/5
public ActionResult Details(int id)
{
var currentBikes = bikes[id];
return View(currentBikes);
}
//
// GET: /Bike/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Bike/Create
[HttpPost]
public ActionResult Create(FormCollection collection)
{
Bike b = new Bike
{
Manufacturer = collection["Manufacturer"], Gears = collection["Gears"], Frame = collection["Frame"]
};
bikes.Add(b);
try
{
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /Bike/Edit/5
public ActionResult Edit(int id)
{
return View(bikes.Where(b => b.BikeID == id).First());
}
//
// POST: /Bike/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /Bike/Delete/5
public ActionResult Delete(int id)
{
return View();
}
//
// POST: /Bike/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
try
{
// TODO: Add delete logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
public int bike { get; set; }
}
}
You need to explicitly convert string to int.
Try following line
Manufacturer = collection["Manufacturer"], Gears = int.Parse(collection["Gears"]), Frame = collection["Frame"]
I would like to get into the habit of using ViewModels.
In the past I have only used them in my Create Actions and I never figured how to use them in Edit Actions. I used Domain Entities instead.
Let's say I have the following:
Using Entity Framework Code First
POCO class in Domain project
public class Person
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int PersonId { get; set; }
public string Name { get; set; }
public string Website { get; set; }
public DateTime? Created { get; set; }
public DateTime? Updated { get; set; }
}
In my Data Project
Abstract Folder:
public interface IPersonRepository
{
IQueryable<Person> People{ get; }
void SavePerson(Person person);
}
Concrete Folder:
EfDb class
public class EfDb : DbContext
{
public EfDb() : base("DefaultConnection") {}
public DbSet<Person> People{ get; set; }
}
EfPersonRepository class
#region Implementation of Person in IPersonRepository
public IQueryable<Person> People
{
get { return _context.People; }
}
public void SavePerson(Persona person)
{
if (person.PersonId == 0)
{
_context.People.Add(person);
}
else if (person.PersonId> 0)
{
var currentPerson = _context.People
.Single(a => a.PersonId== person.PersonId);
_context.Entry(currentPerson).CurrentValues.SetValues(person);
}
_context.SaveChanges();
}
#endregion
PersonCreateViewModel in WebUI Porject ViewModels folder
public class PersonCreateViewModel
{
[Required]
[Display(Name = "Name:")]
public string Name { get; set; }
[Display(Name = "Website:")]
public string Website { get; set; }
}
Person Controller and Create Action:
public class PersonController : Controller
{
private readonly IPersonRepository _dataSource;
public PersonController(IPersonRepository dataSource)
{
_dataSource = dataSource;
}
// GET: /Association/
public ActionResult Index()
{
return View(_dataSource.Associations);
}
// GET: /Person/Details/5
public ActionResult Details(int id)
{
return View();
}
// GET: /Person/Create
[HttpGet]
public ActionResult Create()
{
return View();
}
// POST: /Person/Create
[HttpPost]
public ActionResult Create(PersonCreateViewModel model)
{
if (ModelState.IsValid)
{
try
{
var Person = new Person
{
Name = Model.Name,
Website = model.Website,
Created = DateTime.UtcNow,
Updated = DateTime.UtcNow
};
_dataSource.SavePerson(person);
return RedirectToAction("Index", "Home");
}
catch
{
ModelState.AddModelError("", "Unable to save changes. ");
}
}
return View(model);
}
}
Now unless I am mistaken, I expect my PersonEditViewlModel to look exactly like my PersonCreateViewlModel. But I can't figure out how to use that in my Edit action, provided I also have to call SavePerson(Person person) like I did in my Create action.
Note: Please no suggestions of AutoMapper or ValueInjecter.
How is this done?
It'll be just like create except you need the record Id.
[HttpGet]
public ActionResult Edit(int id)
{
var personVm = _dataSource.People.Single(p => p.PersonId == id)
.Select(e => new PersonEditViewModel {
e.PersonId = p.PersonId,
e.Name = p.Name,
e.Website = p.Website
...
});
return View(personVm);
}
[HttpPost]
public ActionResult Edit(PersonEditViewModel model)
{
if (ModelState.IsValid)
{
var person = _dataSource.People.Single(p => p.PersonId == model.PersonId);
person.Name = model.Name;
person.Website = model.Website;
...
_dataSource.EditPerson(person);
return RedirectToAction("Index", "Home");
}
return View(model);
}
Edit:
So you don't do another query on edits
public void EditPerson(Person person)
{
_context.Entry(person).State = EntityState.Modified;
_context.SaveChanges();
}