How to pass the delegate object to MVC Views.? - asp.net-mvc

I have an delegate in my controller And I want that to be passed to my views to pass into my settings.
I have tried assigning delegates to ViewData["delegateFunction"]=delegateFunction;
But That too is not valid idea..
I know this is a basic Question. But just learning about delegates.
Thanks in advance,
saravanakumar.

I use the Model class for passing delegates to the View:
Model
public class ExampleModel
{
public Func<string, string> getUIName { get; set; }
}
Method declaration
public string concreteMethod_GetUIName(string text)
{
return text;
}
Controller
public ActionResult Index()
{
ExampleModel model = new ExampleModel { getUIName = concreteMethod_GetUIName };
return View(model);
}
View
#model ExampleModel
#Model.getUIName("sample text")

Related

How to pass more than one object to the view in mvc?

I want to pass more than one object in the view. I have two object. One name is "Caller" and one Name is "Receiver". I am new in MVC. This is my action method.
public ActionResult IsActiveCaller(int id)
{
var caller = new CallerService().getCallerById(id);
if(caller.active)
{
var reciver= new reciverService().getReviverTime(caller.dialNo);
return (caller ) // here i also want to send reciver to view
}
return View();
}
Is there any way to send more than object in view?
Yes you can do this. There are multiple ways to do this.
1) You can use viewBag to pass the data or object into view.
You can see here to see how to use viewBag in mvc
2) you can use ViewData but it is not a good approach.
3) you can make ViewModel like as below (recomended)
public class callerReciver
{
public Caller caller {set;get;}
pblic Reciver eciver {set;get;}
}
Now pass callerReciver to view.You can access both object.hope you will understand.
4) Another way is to use partial view.You can make partial view to use more than one object in same view.
You can use a View Model:
public class MyViewModel
{
public Caller Caller { get; set; }
public Receiver Receiver { get; set; }
}
Then you can populate the view model this way:
public ActionResult IsActiveCaller(int id)
{
var caller = new CallerService().getCallerById(id);
var vm = new MyViewModel {
Caller = caller
};
vm.Receiver = caller.active ? new reciverService().getReviverTime(caller.dialNo) : null;
return View(vm);
}
View:
#model MyViewModel
<h1>#Model.Caller.Title</h1>
#if(Model.Receiver != null) {
<h1>#Model.Receiver.Title</h1>
}
The cleanest way is to pass by a view model :
ViewModel
public class MyViewModel {
public Caller MyCaller { get;set; }
public Receiver MyReceiver { get;set; }
}
Controller
public ActionResult IsActiveCaller(int id)
{
var caller = new CallerService().getCallerById(id);
var viewModel = new MyViewModel();
viewModel.MyCaller = caller;
if(caller.active)
{
var reciver= new reciverService().getReviverTime(caller.dialNo);
viewModel.MyReceiver = reciver;
}
return View(viewModel);
}
View
#model MyViewModel
<h1>#Model.MyCaller.Id</h1>
<h1>#Model.MyReceiver.Id</h1>

Reusing code in controllers

I have a block of code which is use in pretty much every controller, so I am wondering how, or what's the best practice for reusing code in multiple controllers
Simple example would be this
public String CoolCode(){
// Stuff
return MyStuff;
}
Then in another controller I just use
string something = CoolCode();
Where should I put it, and how to use it in every controller?
Personally I would inject the helper class into the controller:
public interface IHelper
{
string CoolCode();
}
public class Helper : IHelper
{
public string CoolCode()
{
return "Cool code";
}
}
public class SomeController
{
private IHelper _helper;
public SomeController(IHelper helper)
{
_helper = helper;
}
public ActionResult Index()
{
//call _helper.CoolCode();
}
}
Then you would need to inject this using some sort of IoC container, I recommend Castle Windsor
This is all quite abstract but I recommend you read up on it:
http://www.codeproject.com/Articles/560798/ASP-NET-MVC-Controller-Dependency-Injection-for-Be
What you should do is extend the Controller class that all your controllers inherit now and use this abstraction to wrap all of your controllers that use that code:
public class MyControllerBase : Controller
{
public string CoolCode() { ... }
}
now you simply inherit your abstraction rather than the default one:
public class AnyController : MyControllerBase
{
...
}
However depending on what you need precisely different approaches might be more appropriate.
public interface IBaseUserController
{
string SomePropety { get; set; }
ActionResult SignUp(string code, [Form] SomeViewModel model);
}
public class BaseUserController : Controller, IBaseUserController
{
private static string _somePropety = "";
public BaseUserController(){}
public string SomePropety
{
get
{
return _somePropety;
}
set { _somePropety = value; }
}
public virtual ActionResult SignUp(string code, [Form] SomeViewModel model)
{
// ... CoolCode maybe use SomePropety
return View(model);
}
}
public class TestUserController : BaseUserController
{
public TestUserController()
{
SomePropety = "Value";
}
public override ActionResult SignUp(string code, [Form] SomeViewModel model)
{
return base.SignUp(code, model);
}
public ActionResult SignUp2(string code, [Form] SomeViewModel model)
{
return base.SignUp(code, model);
}
}
MVC controller are same as normal class and controller have the same extension .cs
So use can use static method like following.
HomeController objHomeController = new HomeController();
string something= objHomeController.CoolCode();

ViewBag in static method of controller

I am new to mvc and I load ViewBag in a method of controller as,
HomeController: Controller
{
Public ActionResult Index()
{
loadViewBag();
return View();
}
public void loadViewBag()
{
ViewBag.aaa = "something";
}
}
It works fine.
What is my problem is, Now I want to call loadViewBag() method form another controller( say Account) so that I can reuse same method and need to make loadViewBag() method static due to some static variables as:
public static void loadViewBag()
If I make loadViewBag method static, there appear error on ViewBag " An object reference is required for the non-static field, method, or property 'System.Web.Mvc.ControllerBase.ViewBag.get' ".
Is there any solution/suggestion.
Thank You.
Just make it an extension method of ControllerBase e.g.
public static void ControllerExt
{
public static void LoadViewBag(this ControllerBase controller)
{
controller.ViewBag.aaa = "something";
...
}
}
That way you can use it in any controller
public class HomeController : Controller
{
public ActionResult Index()
{
this.LoadViewBag();
return View();
}
}
public class AccountController : Controller
{
public ActionResult Index()
{
this.LoadViewBag();
return View();
}
}
If its only specific to some controllers then it would be more flexible to pass the ViewBag property in e.g.
public static class ControllerHelper
{
public static void LoadViewBag(dynamic viewBag)
{
viewBag.aaa = "something";
}
}
public class HomeController : Controller
{
public ActionResult Index()
{
ControllerHelper.LoadViewBag(ViewBag);
return View();
}
}
ViewBag is a property of your controller (more specifically of ControllerBase), and since a static method has no knowledge of a class instance, you can't access it.
You could pass the controller instance to the method if you want to use a static method or even make it an extension method, but depending on your problem, this solution could be sub-optimal. You may be able to get a better answer if you add more details to your question.
Public ActionResult Index()
{
this.loadViewBag();
return View();
}
public static void loadViewBag(this ControllerBase target)
{
target.ViewBag.aaa = "something";
}
Do you need that to allow different controllers/views to use some common properties?
Then I'd rather recommend a common base controller, while also wrapping ViewBag code into type safe properties (to let the compiler control the data consistency - as you know, ViewBag is not type safe, so any typos and data mismatches won't be noticed until the code gets executed).
1. Introduce a common controller with those wrapper properties
public abstract class MyBaseController : Controller
{
internal long CurrentUserId
{
get { return ViewBag.CurrentUserId; }
set { ViewBag.CurrentUserId = value; }
}
internal Role CurrentUserRole
{
get { return ViewBag.CurrentUserRole; }
set { ViewBag.CurrentUserRole = value; }
}
...
}
Thus, your inherited controllers could simply set the properties - or, with lots of common code just introduce a method in your base controller - similar to what you already have.
2. Introduce a common view class with those wrapper properties
public abstract class MyBaseViewPage<T> : WebViewPage<T>
{
public string Title
{
get { return (string)ViewBag.Title; }
set { ViewBag.Title = value; }
}
public long CurrentUserId
{
get { return (long)ViewBag.CurrentUserId; }
}
public Role CurrentUserRole
{
get { return ViewBag.CurrentUserRole; }
}
}
public abstract class MyBaseViewPage : MyBaseViewPage<dynamic>
{
}
and update web.config to let MVC know you're using a custom base view:
<configuration>
...
<system.web.webPages.razor>
...
<pages pageBaseType="MyRootNamespace.Views.MyBaseViewPage">
...
</pages>
</system.web.webPages.razor>
Now you can use them as normal properties in your controllers and views.

How to get Controller Name and its properties in another class?

I am developing a MVC application.
I want to send a controller for validating purpose to Validation class.
That class will validate the controllers properties and send the result.
I am not gettting, how to get name and properties of the controller after
getting it in class.
Below code is the Controller class code and I send this controller to class named validation class.
[HttpPost]
public ActionResult Create(Location location)
{
if (ModelState.IsValid)
{
Validations v = new Validations();
Boolean ValidProperties = true;
//Sends the controller to Validation class
v.ValidProperty(this);
if (ValidProperties == true)
{
db.Locations.Add(location);
db.SaveChanges();
return RedirectToAction("Index");
}
}
}
And Below code is the class named Validations where I want to validate the controller .
Now I am not getting how to get the name of controller and its properties.
public class Validations
{
string PropertName;
public void ValidProperty(Controller ctr)
{
var name1 = ctr;
string s = ctr. ????????
//How to get Controller Name and its properties ?
}
}
use reflection to get name as:
var name = this.GetType().Name;
Or you can create a custom base controller of your choice, add properties, methods to it and deal with derived controllers as:
public abstract class BaseController : Controller
{
// add other properties as needed
public abstract string Name { get; protected set; }
public virtual void ValidProperty()
{
string s = Name;
//something esle
}
}
public class YourController : BaseController
{
private string _name;
public override string Name
{
get { return _name; }
protected set { _name = "Your_Name"; }
}
[HttpPost]
public ActionResult Create(Location location)
{
if (ModelState.IsValid)
{
bool validProperties = true;
// Deals with a base controller method
ValidProperty();
// or something like this, if you prefer
var controller = (BaseController) this;
Validations v = new Validations();
//Sends the controller to Validation class
v.ValidProperty(controller);
if (validProperties)
{
db.Locations.Add(location);
db.SaveChanges();
return RedirectToAction("Index");
}
}
return Content(string.Empty);
}
}

Accessing a database object (and other important data) in the View

I know it's a bad practice to use database in the view. However, I'm also passing the User object and I wonder how I can make it easy to use.
I love the way it works in Ruby On Rails. You just create an #instance_variable in before_filter and call it from the controllers and from the views.
You can't do this in ASP.NET MVC though. So I created a class with all the data I need to pass to the view (DataContext and User):
public class XData
{
public DBDataContext DB { get; set; }
public User User { get; set; }
}
In controller's Initialize method I get all the data:
public XData X;
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
X = new XData();
X.DB = ...;
X.User = ....;
}
Works great: I can get the database object from the view like this:
<%= Model.X.DB.Users.First().Name %>
In order to pass the data to the view, I have to do the following:
public ActionResult Foo()
{
return View(new FooModel
{
X = X,
HelloMessage = "Hello world!"
});
}
The thing I don't like here is that I always have to write the X = X thing. How can I initialize that automatically?
Thanks
I've seen a similar problem where a lot of controllers return a similar model with only a few customizations. In this case, create an abstract base model that other models derive from, and a function that returns the particular model you need with the base X = X and so forth already set.
For example, consider this:
public abstract class MyBaseModel
{
public User User { get; set; }
}
public class FooModel : MyBaseModel
{
public string FooMessage { get; set; }
}
public class BarModel : MyBaseModel
{
public string BarMessage { get; set; }
}
public class MyController : Controller
{
public ActionResult Foo()
{
var model = this.GetModel<FooModel>();
// Set the properties on FooModel.
model.FooMessage = "Hello world!"
return View(model);
}
public ActionResult Bar()
{
var model = this.GetModel<BarModel>();
// Set the properties on BarModel.
model.BarMessage = "Hello world 2!"
return View(model);
}
protected T GetModel<T>() where T : MyBaseModel, new()
{
T model = new T();
// Set the properties on MyBaseModel.
model.User = ...;
return model;
}
}
If you want to share MyBaseModel and GetModel among many controllers, extract it out to a ModelProvider or something similar that is supplied to each controller, ideally through dependency injection.
You could place X in ViewData and write an HtmlHelper extension method to access X or override the View method of the controller and add a little reflection logic that maps every instance property of the controller to properties with matching names of your model (I guess Automapper could help here...)
I think you'll need to start by making your view strongly typed:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Namespace.XData>" %>
and in your controller:
public ActionResult Foo()
{
var X = new XData();
X.User = ....;
X.SomeProperty = ...;
X.Message = "Hello world!";
return View(X);
}
which allows you to access the object in your view like so:
<%: Model.User.UserName %>
<%: Model.Message %>

Resources