I'm looking at the N2 CMS Minimal Example for MVC (from here)
I've figured out most of it, but I see that N2 supports 'Parts' that you can drop into 'Zones'.
How do I get Zones and Parts working in the minimal example?
The Html.Zone() command doesn't seem to work out-of-the-box.
With a bit of help from libardo at the N2 forum
Here's the 'minimal' way of adding Zones and Parts to the N2 Minimal Example for MVC:
1) Add this namespace in the web.config pages.namespaces node:
<pages>
<namespaces>
...
<add namespace="N2.Web.Mvc.Html"/>
...
2) Add a Container page model, using the AvailableZones attribute:
using N2.Integrity;
...
[Definition("ContainerPage")]
[AvailableZone("Right", "MyRightZone")]
public class ContainerPage : N2.ContentItem
{
...
3) Add Container controller in the usual N2 manner, nothing special needed here to make it a container:
[Controls(typeof(ContainerPage))]
public class ContainerController : ContentController<ContainerPage>
{
...
4) In the view for the container, use the Html.DroppableZone function:
<div class="n2zone">
<% Html.DroppableZone("MyRightZone").Render(); %>
</div>
5) Add a part model, e.g. this one just shows Title as a string. Note that PartDefinition is what makes it a Part that can be dropped into a Zone:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using N2;
using N2.Details;
namespace MyProject.Models
{
[PartDefinition("SimplePart")]
[WithEditableTitle("Title", 10)]
public class SimplePart : ContentItem
{
[DisplayableLiteral()]
public override string Title
{
get { return base.Title; }
set { base.Title = value; }
}
}
}
6) Add a Controller for the Part. This is the usual N2 controller except that we override Index to return a PartialView:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using N2.Web;
using N2.Web.Mvc;
using MyProject.Models;
namespace MyProject.Controllers
{
[Controls(typeof(SimplePart))]
public class SimplePartController : ContentController<SimplePart>
{
public override ActionResult Index()
{
return PartialView(CurrentItem);
}
}
}
7) Finally, add a partial view for the Part controller. Nothing special is needed here:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MyProject.Models.SimplePart>" %>
<div class="simplePart">
<%= Html.DisplayContent(m => m.Title) %>
</div>
In the N2 editor you can then drop as many SimpleParts as you like into the ContainerPage pages.
Related
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
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
}
}
}
I'm working on setting up separate projects for my Areas in my main MVC project. I followed the guide here:
https://stackoverflow.com/a/12912161/155110
I set breakpoints during the launch and can see that the RazorGeneratorMvcStart is being hit as well as the AreaRegistration that sets up the routes. RazorGenerator.Mvc is installed and the Custom Tool on my cshtml pages is set to use it. When I access the Area URL after launching my main project, I can see that it hits the controller in the separate Area project, however, I cannot get it to find the view. I get the following which a huge list of locations:
[InvalidOperationException: The view 'Index' or its master was not
found or no view engine supports the searched locations. The following
locations were searched:
STARAreaRegistration.cs
using System.Web.Mvc;
namespace AreaSTAR.Areas.STAR
{
public class STARAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "STAR";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"STAR_default",
"STAR/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
}
RazorGeneratorMvcStart.cs
using System.Web;
using System.Web.Mvc;
using System.Web.WebPages;
using RazorGenerator.Mvc;
[assembly: WebActivatorEx.PostApplicationStartMethod(typeof(AreaSTAR.RazorGeneratorMvcStart), "Start")]
namespace AreaSTAR {
public static class RazorGeneratorMvcStart {
public static void Start() {
var engine = new PrecompiledMvcEngine(typeof(RazorGeneratorMvcStart).Assembly) {
UsePhysicalViewsIfNewer = HttpContext.Current.Request.IsLocal
};
ViewEngines.Engines.Insert(0, engine);
// StartPage lookups are done by WebPages.
VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);
}
}
}
Areas/STAR/Controllers/DefaultController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace AreaSTAR.Areas.STAR.Controllers
{
public class DefaultController : Controller
{
// GET: STAR/Default
public ActionResult Index()
{
return View();
}
}
}
Areas/STAR/Views/Default/Index.cshtml:
#* Generator: MvcView *#
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>View1</title>
</head>
<body>
<div>
Index view
</div>
</body>
</html>
URL accessed when seeing the View not found error: http://localhost:53992/STAR/Default/Index
This was because I accidentally installed the RazorEngine.Generator extension and set the custom tool to RazorEngineGenerator instead of installing the Razer Generator extension and setting the custom tool to RazorGenerator.
In the following code I'm trying to return a view with an integer as its type. The code below doesn't work. What am I missing?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcApplication5.Controllers
{
public class HomeController : Controller
{
public ActionResult Index(int answer)
{
int row = 2;
int col = 1;
answer = row * col ;
return View(answer);
}
}
}
public ActionResult Index(int answer)
{
int row = 2;
int col = 1;
int answer = row * col ;
return View(answer);
}
and then ensure your view is strongly typed to int:
<%# Page
Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<int>"
%>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
The answer is: <em><%= Html.DisplayForModel() %></em>
</asp:Content>
There is nothing wrong with the code you posted.
The error must be related to something else.
If you want to know the cause of the error it would help to indicate what error you are receiving, as well as stack information.
You're likely requesting the action URL without specifying an answer parameter. Change your method signature to the following and it should all work:
public ActionResult Index()
As I can see, you're trying to open the URL http://localhost:8080/Home/Index and the problem is that the action "Index" have a parameter called answer.
Try to call http://localhost:8080/Home/Index?answer=10 and you'll see that it will work.
edit:
as Darin said, make sure that the Index.aspx exists.
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