I am new to ASP.net having been a PHP coder for 10 years. The MVC makes sense to be as I find it quite similar to Laravel.
I am trying to find the best solution for storing and serving meta data to my web pages in my ASP.net MVC 4 project. From what I have read I have concluded to use the following method.
Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace project.Models
{
public class Meta
{
public String Title { get; set; }
public String Description { get; set; }
public String Keywords { get; set; }
public String H1 { get; set; }
public String H2 { get; set; }
public String Robots { get; set; }
}
}
Controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace project.Controllers
{
public class AboutController : BaseController
{
public ActionResult Index()
{
ViewData["metaTitle"] = "About us";
ViewData["metaDescription"] = "";
ViewData["metaKeywords"] = "";
ViewData["pageH1"] = "About";
ViewData["PageH2"] = "";
return View();
}
}
}
View
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>project | #ViewData["metaTitle"]</title>
<meta name="description" content="#ViewData["metaDescription"]">
<meta name="keywords" content="#ViewData["metaKeywords"]">
<meta name="robots" content="#ViewData["metaRobots"]">
The problem I have actually comes in one of my other views where I am trying to build a breadcrumb trail. At the moment I can get the controller/action name to appear in the breadcrumb, however I wish to access the view data for those controller/actions.
I can't find anywhere that explains how to do it/if it is possible.
Therefore;
Either I am going about storing meta data wrong, if so tell me a better way to do it.
else please outline a way to access a controllers ViewData
Please provide code samples or resources that accurately explain how to do it
Many thanks for your time.
I would do something like below,
1) Create a base class model and this base model will be derived in other models.
public class BaseModel
{
public String Title { get; set; }
public String Description { get; set; }
public String Keywords { get; set; }
public String H1 { get; set; }
public String H2 { get; set; }
public String Robots { get; set; }
}
About Model class
public class AboutModel : BaseModel
{
public string AboutDescription { get; set; }
}
2) Create a Intialize method in BaseController class which will set the properites for Title and description for your model.
public class BaseController : Controller
{
public BaseModel Initialize(BaseModel model)
{
model.Title = "Title";
model.Description = "Desc";
return model;
}
}
3) In About controller, you would need to call the initialize method like below.
public class AboutController : BaseController
{
public ActionResult Index()
{
//create instance for About Model
var model = new AboutModel();
Initialize(model);
model.AboutDescription = "About Description";
return View(model);
}
}
4) In _Layout.cshtml class you need to use the BaseModel class
#model <YourNameSpace>.BaseModel
<title>#Model.Title</title>
5) Other views ex : About.cshtml
#model <YourNameSpace>.AboutModel
I would recommend not to use ViewData for handling Common site properties like Title / Meta tags. This way your code will be much cleaner...
Since you are deriving the base class model to the other views and Initializing the Initialize method in all the ActionResults method you should get the title description properties across the pages / views.
Related
I've got this task requiring building a parent/child view in html. NOT USING ANY PLUGINS!
I've created a database and a model (H_Table), and a class (Element) in controller for child nodes.
But how do I get this to work together. So, that it retrieves data from the model passes it to the class and returns to view as model. I'm not really sure whether I explaied it right. Ask away.
My Model:
namespace Tree_List.Models
{
using System;
using System.Collections.Generic;
public partial class H_Table
{
public int ID { get; set; }
public string NAME { get; set; }
public Nullable<int> PARENT_ID { get; set; }
}
}
My Controller:
using System.Collections.Generic;
using System.Web.Mvc;
using Tree_List.Models;
namespace Tree_List.Controllers
{
public class ListController : Controller
{
// GET: List
private Models.ListDBEntities1 db_connection = new Models.ListDBEntities1();
public ActionResult Index()
{
var Items = db_connection.H_Table;
return View(Items);
}
}
public partial class Element
{
public int ID { get; set; }
public string NAME { get; set; }
public List<Element> CHILDS { get; set; }
}
}
If I get your question right you want to render this hierarchical data of yours in a view. To do that you have to use Javascript and jQuery to render this data there are tons of ready libraries and open source examples on how to do this like:
https://www.codeproject.com/tips/696985/how-to-create-treeview-in-mvc
https://www.mindstick.com/Articles/1119/using-treeview-in-asp-dot-net-mvc
You can see them and write one yourself like them. Also take a look at more abstracted tool from Telerik.
Hope it helps :)
Short question: what's the proper way to have common, site-wide, properties that are:
Accessible in both _layout.cshtml and other views
Strongly typed, ie. Model.TextInUserLanguage
And at the same time still allows custom controllers to their own model?
In other words, how to tell asp.net to:
Use CommonModel with _layout.cshtml by default
When accessing a controller C that has its own model M / view V, apply model M to view V (while still respecting rule #1)
Long story
I created a sample asp.net MVC 4 webapp, which has the HomeController and AccountController by default
HomeController.cs
public ActionResult Index()
{
CommonModel Model = new CommonModel { PageTitle = "HomePage" };
return View(Model);
}
BaseModel.cs
public abstract class BaseModel
{
public string AppName { get; set; }
public string Author { get; set; }
public string PageTitle { get; set; }
public string MetaDescription { get; set; }
...
}
CommonModel.cs
public class CommonModel: BaseModel
{
public CommonModel()
{
AppName = Properties.Settings.Default.AppName;
Author = Properties.Settings.Default.Author;
MetaDescription = Properties.Settings.Default.MetaDescription;
}
}
_layout.cshtml
#model K6.Models.BaseModel
<!DOCTYPE html>
<html>
<head>
<title>#Model.PageTitle - #Model.AppName</title>
...
The problem is, this approach:
Really feels hacky
I have to change every controller in my webapp so that they use this CommonModel in order to make _layout.cshtml recognize my custom properties, but at the same time this requires significant work in order to make things work when dealing HTTP Posts, showing lists, etc...
There must be other way to do this. I'm new to asp.net MVC, so what's the best way to do this about having to use ViewBag?
The first that comes to mind for me is something static
public static class ServerWideData {
private static Dictionary<string, Data> DataDictionary { get; set; } = new Dictionary<string, Data>();
public static Data Get(string controllerName = "") { // Could optionally add a default with the area and controller name
return DataDictionary[controllerName];
}
public static void Set(Data data, string name = "") {
DataDictionary.Add(name, data);
}
public class Data {
public string PropertyOne { get; set; } = "Value of PropertyOne!!";
// Add anything here
}
}
You can add data from anywhere by calling
ServerWideData.Set(new Data() { PropertyOne = "Cheese" }, "Key for the data")
And retrieve it anywhere with
ServerWideData.Get("Key for the data").PropertyOne // => Cheese
Hey Guys I hava a question. I know questions like this are asked often, but I worked on a solution for several hours and read many answers but I couldnt find the right one. I am doing an application using ASP.NET MVC 4 Razor. I´m rather new to this system. I created a .edmx Data Model using Entity Framework 5 (Database-First Approach). This is how my auto-generated Context class looks like:
namespace KSM3.Models
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Linq;
public partial class kontrollsystemEntities : DbContext
{
public kontrollsystemEntities()
: base("name=kontrollsystemEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
[EdmFunction("kontrollsystemEntities", "udf_GetReportsByController")]
public virtual IQueryable<udf_GetReportsByController_Result> udf_GetReportsByController(string controller_account)
{
var controller_accountParameter = controller_account != null ?
new ObjectParameter("controller_account", controller_account) :
new ObjectParameter("controller_account", typeof(string));
return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<udf_GetReportsByController_Result>("[kontrollsystemEntities].[udf_GetReportsByController](#controller_account)", controller_accountParameter);
}
}
}
and my Model class looks like this:
namespace KSM3.Models
{
using System;
public partial class udf_GetReportsByController_Result
{
public int ID { get; set; }
public string ProviderID { get; set; }
public int VertragID { get; set; }
public System.DateTime Leistungszeitraum_von { get; set; }
public System.DateTime Leistungszeitraum_bis { get; set; }
public string ReportklasseID { get; set; }
public int Version { get; set; }
public string Status { get; set; }
}
}
When I now click on "Add Controller" and select my classes, I get the error message:
"Unable to retrieve Metadata for KSM3.Models.udf_GetReportsByController_Result.cs"
Note: I am using Entity Framework to retrieve information from a user-defined function, not from a table! If I try the same procedure with a table, it works!
What do I have to prepare or change in order to make this work?
Thank you for all answers!
I have solved my problem, thanks!
I had to call the udf_GetReportsByController(string controller_account) method in the controller and hand the IQueryable-Result to my view.
My Controller looks like these (Note: Beginner´s mistake)
public class ReportController : Controller
{
private kontrollsystemEntities db = new kontrollsystemEntities();
//
// GET: /Report/
public ActionResult Index()
{
IQueryable<udf_GetReportsByController_Result> result = db.udf_GetReportsByController(User.Identity.Name);
return View(result.ToList());
}
}
}
I have the following view models:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public BankAccount BankAccount { get; set; }
public PayPalAccount PayPalAccount { get; set; }
}
public class BankAccount
{
public string BankName { get; set; }
public string AccountNumber { get; set; }
}
public class PayPalAccount
{
public string PayPalEmail { get; set; }
}
In my single view I have a form that binds the Person model and also has a DropDownList that let's the user choose an account type.
Once the user makes his choice, I load dynamically using jQuery ajax one of the partial views that represent either the BankAccount or the PayPalAccount and I add it to the page.
After the user clicks submit, I call this action:
public ActionResult Save(Person person)
{
// Here I expect that either person.BankAccount or person.PayPalAccount
// will contain the user input, and the other will be null
}
How do I make the partial view properties bind to the nested property in my Person view model?
Your form fields must be prefixed (with BankAccount. or PayPalAccount.) so that they can be automatically bound.
When you return your partial view from Ajax, withthe current model you're using, their names don't have a prefix.
The easier way to prefix them is using exactly the same View Model class: Person for both partial views. If you do that, in the Razor you'll have to write
#Html.EditorFor(m => m.BankAccount.BankName)
The generated input field will have the required prefix BankAccount., i.e. it will look like this: <input ... name='BankAccount.BankName' ... />
You could also create a view model like this for your partial:
public class BakAccountModel
{
// make sure the property name is the same as in the Person view model
public BankAccount { get; set; }
}
An finally, you can try a solution like this:
ASP.NET MVC partial views: input name prefixes
I can't assure the last solution will work fine: for example it could break the ModelState. And is harder to implemente and "less standard".
Problem is: I want to run 3 different actions but instead of that i want to fed all data from single action in a bigger model.
I am using:
public class SearchScrapClass
{
public WClass WClass { get; set; }
public SClass SClass { get; set; }
public YClass YClass { get; set; }
}
public class WClass
{
public string title { get; set; }
public string link { get; set; }
}
public class SClass
{
public string title { get; set; }
public string link { get; set; }
}
public class YClass
{
public string title { get; set; }
public string link { get; set; }
}
I am using LINQ to add data in these models.
I am using :
var wikians = from info in document.DocumentNode.SelectNodes("//div[#id='span']")
from link in info.SelectNodes("div//a").Where(x => x.Attributes.Contains("href"))
select new SearchScrapClass //Main Bigger Class
{
WClass.link= link.Attributes["href"].Value, //ERROR: How to add to WClass's url ?
WClass.title= link.InnerText //ERROR: How to add to WClass's url ?
}
var wikians = from info in document.DocumentNode.SelectNodes("//div[#id='results']")
from link in info.SelectNodes("p//a").Where(x => x.Attributes.Contains("href"))
select new SearchScrapClass //Main Bigger Class
{
YClass.link= link.Attributes["href"].Value, //ERROR: How to add to YClass's url ?
YClass.title= link.InnerText //ERROR: How to add to YClass's url ?
}
//Also for the 3rd class (model)
return View(wikians); //and then return bigger class model so that i can access them in view
This is one way i want to add data to link and title of all the classes.
My try is to add data to all 3 classes from different sources and pass the bigger model to view so that i can access all the classes as:
#model SearchScrapClass
#using(Html.BeginForm()) {
#Html.EditorFor(o => o.WClass.link)
...
}
Please suggest a way
Thanks
To Expand on my comment, I would suggest creating a ViewModel folder for organization sake. in this add the view model
public class SearchScrapClassViewModel
{
SearchScrapClass searchScrap;
WClass wClass;
SClass sClass;
YClass yClass;
}
In your controller then you instantiate the new viewmodel
SearchScrapClassViewModel model = new SearchScrapClassViewModel
{
....add in your logic to fill your class objects here
}
return view(model);
then in your view add the using for the viewmodel.
#using SearchScrapClassViewModel
You can pass multiple model by creating a new model class which will contain multiple objects.
public class MultiModel
{
SearchScrapClass searchScrap;
WClass wClass;
SClass sClass;
YClass yClass;
}
See the tuple tutorial http://www.dotnetperls.com/tuple or this one http://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx
Like controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var first = new FirstModel();
var second = new SecondModel();
return View(Tuple.Create(first,second));
}
}
And the view:
#model Tuple
<div>
#Model.Item1.FirstModelProp
#Model.Item2.SecondModelProp
</div>
SearchScrapClassViewModel model = new SearchScrapClassViewModel
{
....add in your logic to fill your class objects here
}
what logic we apply here " ....add in your logic to fill your class objects here"