How to create a strongly typed MVC View based on a custom Linq2Sql class - asp.net-mvc

I have created a custom entity because I need to populate an entity with some data from a join in L2S.
When I right click on the ActionResult code in the Controller to "Add View", and then choose "Create strongly typed view", my class doesn't show up in the classes available in the selector. I'm not sure why. Here is my code:
//The Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
namespace FurnitureStore.Models.Repository
{
public class FurnitureRepository
{
public IQueryable<Listing> GetProductListings()
{
FurnitureDataContext dc = new FurnitureDataContext();
return (from p in dc.Products
join c in dc.Categories
on p.CategoryId equals c.CategoryId
select new Listing
{
ProductName = p.ProductName,
CategoryDescription = c.CategoryDescription
});
}
}
}
//The entity class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace FurnitureStore.Models
{
public class Listing
{
public string ProductName { get; set; }
public string CategoryDescription { get; set; }
}
}
//The Method in the Controller
public ActionResult ProductListings()
{
FurnitureRepository fr = new FurnitureRepository();
var listings = fr.GetProductListings();
return View("ProductListings",listings);
}

Make sure that you compile the code, if the code is not compiled the newly added classes dont showup in the classes available in the selector

Just create a normal view and edit the view's page definition (inherits attribute specifically) yourself.
<%# Page ... Inherits="System.Web.Mvc.ViewPage<IQueryable<FurnitureStore.Models.Listing>>" %>
Off the top of my head I can't answer why it isn't appearing in your class selector.
HTHs
Charles

Related

Razor Pages SelectList Won't Populate

My Branch SelectList won't populate with data.
The query does return 15 records, but they are not binding to the Select control.
Any thoughts?
This is what appears in the HTML page results for asp-items, instead of the items. Why does this get added tp asp-items? System.Collections.Generic.List`1[Microsoft.AspNetCore.Mvc.Rendering.SelectListItem]
<select asp-items="System.Collections.Generic.List`1[Microsoft.AspNetCore.Mvc.Rendering.SelectListItem]"
asp-for="Branch"></select>
Here is my HTML Razor Page.
<h5 class="card-title">Choose Branch</h5>
<select id="selectBranches" asp-for="Branch" asp-items="#Model.Branches" disabled="enabled" class="custom-select"></select>
Here is my C# RazorPage.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using SetpointIS.Models;
using SetpointIS.Models.Datawarehouse;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc.Rendering;
public class EditModel : PageModel
{
private DBContextVuPoint db;
public List<SelectListItem> Branches { get; set; }
public EditModel(DBContextVuPoint _db)
{
db = _db;
}
public void OnGet()
{
Branches = db.Branch.Select(a =>
new SelectListItem
{
Value = a.BranchId.ToString(),
Text = "(" + a.Abbreviation + ")" + a.Name
}).ToList();
}
}
In asp-for you wrote Branch instead of 'Branches'

How to fetch all the fields form database in Asp.NET MVC?

I have an application in Asp.NET MVC with Entity Data Model. Now I have a model for state_master table where I have only one property 'State_Name' and in database table I have 2 fields 'State_ID' which is auto incremented and 'State_Name' for which I will insert the data.
Now as I have only one property in Model I am not able to fetch both the fields 'State_ID' and 'State_Name' using this model. This is the issue which I am facing.
State Model File :
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace ViewData.Models
{
public class state_model
{
[Key]
public string state_name { get; set; }
}
}
View File :
#using ViewData.Models
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>state_view</title>
</head>
<body>
<div>
<ul>
#foreach (var state in ViewData["states"] as IList<state_model>)
{
<li>
#state.state_name
</li>
}
</ul>
</div>
</body>
</html>
Controller File :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ViewData.DataAccessLayer;
using ViewData.Models;
namespace ViewData.Controllers
{
public class StateController : Controller
{
// GET: State
public ActionResult Index()
{
DataLayer dl = new DataLayer();
IList<state_model> data = (from o in dl.states select o).ToList();
ViewData["states"] = data;
return View("state_view");
}
}
}
You need to create a View Model for state to fetch and bind all the fields from database. For example,
public class state_ViewModel
{
[Key]
public int state_Id { get; set; } //check with your data type
public string state_name { get; set; }
}
So in your controller method, You can use this one for fetch and bind. And for insert record you can use state_model
And in your action method,
public ActionResult Index()
{
DataLayer dl = new DataLayer();
IList<state_ViewModel> data = (from o in dl.states select o).ToList();
ViewData["states"] = data;
return View("state_view");
}
See, View Model is nothing but rendering your data in your view.
To know more about view model click here

Database first MVC, object not populating

I have to use the Database first approach, the solution has 3 projects. 2 are class libraries the third is the actual MVC project. One class library has the edmx designer. The other has Has different model classes. These 2 libraries are referenced by the MVC project. My problem is that the object is not populating values. I guess it is a naming conflict somewhere. The object tblRDBUser is not getting populated. There is a table in the database with the same object name too. The object attributes match the column names too. I am not getting the values from the view into the controller.
Project one:
RDB.DataModel, it contains the EDMX designer.
Project two: RDB.Models
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RDB.DataModel;
public class Authenticate
{
public string AuthenticateUser(tblRDBUser User)
{
Book_TradEntities users = new Book_TradEntities();
return (from p in users.tblRDBUsers where p.UserName == User.UserName && p.Password == User.Password select p.UserName).FirstOrDefault();
}
}
Project 3:
View:
#model RDB.DataModel.tblRDBUser
#{
ViewBag.Title = "Index";
}
#Html.TextBoxFor(a => a.UserName)
#Html.TextBoxFor(a => a.Password)
#Html.ActionLink("Login", "Authenticate");
Controller:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using RDB.DataModel;
using RDB.Models;
namespace CignaRDB.Controllers
{
public class RDBWebController : Controller
{
//
// GET: /RDBWeb/
public ActionResult Index()
{
return View();
}
public ActionResult Authenticate(tblRDBUser User)
{
if (ModelState.IsValid)
{
Authenticate user = new Authenticate();
user.AuthenticateUser(User);
return View();
}
return View();
}
}
}
The main problem. that you create link #Html.ActionLink("Login", "Authenticate") which after click on him just redirect user to Authenticate method. Insted of a link you should generate button which make submit of you form. So your view code should be something like this
#model RDB.DataModel.tblRDBUser
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("Authenticate"))
{
#Html.TextBoxFor(a => a.UserName)
#Html.TextBoxFor(a => a.Password)
<input type="submit" value="Login" />
}
Also you controller looks strange, maybe because this is result of code simplification, but at least should be next change when your model is invalid (return View("Index");):
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using RDB.DataModel;
using RDB.Models;
namespace CignaRDB.Controllers
{
public class RDBWebController : Controller
{
//
// GET: /RDBWeb/
public ActionResult Index()
{
return View();
}
public ActionResult Authenticate(tblRDBUser User)
{
if (ModelState.IsValid)
{
Authenticate user = new Authenticate();
user.AuthenticateUser(User);
return View();
}
return View("Index");//because view name and Action method not match
}
}
}

MVC c# controller return view()

below is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Models = We.Models;
using We.BAL;
using System.Globalization;
using System.IO;
using System.Text;
using System.Web.Helpers;
using System.Diagnostics.CodeAnalysis;
using System.Security.Principal;
using System.Web.Routing;
using System.Web.Security;
using PagedList;
using We.Models.ViewModels;
using We.Models.Interface;
using We.Models.DBData;
using We.Models.Repository;
using System.Data.Sql;
using System.Data.Query;
using System.Data.SqlClient;
namespace We.Controllers
{
public class ClientEnquiryController : Controller
{
private Models.Interface.IPolicyService _repository;
private Models.Repository.PolicyServiceRepository clientenqRepository;
public ClientEnquiryController()
: this(new Models.Repository.PolicyServiceRepository())
{
}
public ClientEnquiryController(Models.Interface.IPolicyService repository)
{
_repository = repository;
}
public ActionResult MasterView( string PolicyNo, string carrierCode, string sPol, string languageCode)
{
carrierCode = "2";
sPol = "502-0877220";
languageCode = "eng";
return View(_repository.policymaster(carrierCode, sPol, languageCode));
}
From my codeI am do the return like this :
return View(_repository.policymaster(carrierCode, sPol, languageCode));
how about if i want return the view with more than one statement in same time? for example:
_repository.policymaster(carrierCode, sPol, languageCode);
_repository.policyAgent(carrierCode, sPol, languageCode);
Anyone can help me?
I think you might benefit from modelling the view with the two return objects. For example,
public class MasterViewVM
{
public PolicyMaster {get; set;}
public PolicyAgent {get; set;}
}
Then you return the view model with the data entities:
public ActionResult MasterView(string PolicyNo,
string carrierCode, string sPol, string languageCode)
{
carrierCode = "2";
sPol = "502-0877220";
languageCode = "eng";
MasterViewVM model = new MasterViewVM
{
PolicyMaster =_repository.policymaster(carrierCode, sPol, languageCode),
PolicyAgent = _repository.policyAgent(carrierCode, sPol, languageCode)
};
return View(model);
}
Another possibility is to use a child action. See
http://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx

Base controller class

I have a base controller class and I would like to pass a Message from the Base class to all controllers and for that message to be available to all views.
I've created a basic version below...
Section Controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Website.Controllers
{
public class SectionController : Controller
{
//
// GET: /Section/
public ActionResult Section()
{
ViewData["Message"] = "THIS IS A TEST";
return View();
}
}
}
Home Controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Website.Controllers
{
public class HomeController : SectionController
{
public ActionResult Index()
{
return View();
}
}
}
View
<%= Html.Encode(ViewData["Message"]) %>
I know I can do this in the home controller but I'm just testing at the mo.
I'm not getting any errors with the above but I'm also not displaying the message on my view?
I'm using this tutorial http://www.asp.net/LEARN/mvc/tutorial-13-cs.aspx The Good Solution part, if that helps.
Think I've got it working now used the code below on my sectionController...
namespace Website.Controllers
{
public class SectionController : Controller
{
//
// GET: /Section/
public SectionController()
{
ViewData["Message"] = "THIS IS A TEST";
//return View();
}
}
}
Is this an ok solution?
You're setting your ViewData in the Section action method of your base controller, do you actually want to be setting it in the constructor of your base controller?
public SectionController()
{
ViewData["Message"] = "THIS IS A TEST";
}
HomeController.Index isn't calling SectionController.Section.
Because none of the requests are mapped to action "Section" in SectionController. If you mapped a request like domain/Section/Section, you would see your message in your view (Assuming that you are using default routing and have a view named "Section").
What you need to do is, placing your message into the viewdata on a method that runs every time an action is run. You can do it in OnActionExecuting like:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
ViewData["Message"] = "THIS IS A TEST";
base.OnActionExecuting(filterContext);
}
in the SectionController.

Resources