I want to render some Partial Views into the main View. So i used the Ext.Net.ComponentLoader like this:
#(
Html.X().Window()
.Title("Items")
.Width(400)
.Height(300)
.Closable(false)
.Resizable(false)
.Layout(LayoutType.Border)
.Items(i=>{
i.Add(new Panel{
ID = "West1",
Title = "West",
Width=200,
Layout = "Accordion",
Region = Region.West,
Loader = Html.X().ComponentLoader()
.Url(Url.Action("WestItems"))
.Mode(LoadMode.Script)
.Params(new { containerId = "West1" })
});
i.Add(new Panel{
ID = "Center1",
Region = Region.Center,
BodyPadding = 10,
Header = false
});
})
)
the main view here is calling Partial View with action controller "WestItems" which is not good in my case. i want to call partial View directly without action controller like using Html.Partial("_PartialView", Model) also i want to send the Model as parameter to the partial view. Is there any way to call Partial View directly via ComponentLoader? How to send Model as parameter to the Partial View?
We should always call controllers action and they will render partial views.
Partial view are called like:
public PartialViewResult _PartialView(string containerId)
{
...
return new PartialViewResult
{
RenderMode = RenderMode.AddTo,
ContainerId = containerId,
Model = yourModel,
WrapByScriptTag = false
};
}
}
Related
I am using Devexpress MVC application where i used one GridLookup control in shared layout. I needed here some controller which will call a method on every request. For this purpose i used base controller and using ActionExecutingContext method where i am calling my menu loading and gridlookup loading. I am using viewdata to set the value and in shared view i used partial view of my GridLookup control where i am binding viewdata to GridLookup.
Below is the Base controller used to load menu and filters of gridlookup.
protected override void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context);
ProcessingMenus();
}
Below is the shared layout where i am using partialview of gridlookup control
#Html.Partial("_ReportFilter")
Below is the GridLookup control used in this partial:
#{
var gridLookup = Html.DevExpress().GridLookup(settings =>
{
settings.Name = "LookupLobMultiple";
settings.KeyFieldName = "Description";
settings.GridViewProperties.CallbackRouteValues = new { Controller = "Manage", Action = "BindLOB" };
settings.Properties.SelectionMode = GridLookupSelectionMode.Multiple;
settings.Properties.TextFormatString = "{0}";
settings.Properties.MultiTextSeparator = ";";
settings.CommandColumn.Visible = true;
settings.CommandColumn.ShowSelectCheckbox = true;
settings.CommandColumn.SelectAllCheckboxMode = GridViewSelectAllCheckBoxMode.AllPages;
settings.GridViewProperties.SettingsPager.Visible = false;
settings.GridViewProperties.Settings.ShowGroupPanel = false;
settings.GridViewProperties.Settings.ShowFilterRow = false;
settings.Columns.Add("ID").Visible = false;
settings.Columns.Add("Description").Caption = "Line of Business";
settings.PreRender = (s, e) =>
{
MVCxGridLookup gl = (MVCxGridLookup)s;
gl.GridView.Selection.SelectRowByKey(ViewData["LOB"]);
};
});
}
#gridLookup.BindList(ViewData["LobModal"]).GetHtml()
In the above GridLookup control you can see am binding data using viewdata which is loading in ProcessingMenus method.
First issue here is in GridLookup i have used controller and action method also but this is not calling when i check and uncheck any value and showing Loading....
Second issue when after sometime if i again hit the url OnActionExecuting method is not calling due to it menus are not loading again.
I found the answer from Devexpress team is to call partial view in shared view use #{Html.RenderAction("action", "controller");} and then in that action call the partial view that need to show in shared layout with passing model data.
and in partial view just bind the grid with the passed model.
That's it.
Thank you for all your suggestions.
I want to be able to set multiple form(html) objects (Textbox, ActionLink) to either visible = false or enabled = false based on a condition inside the controller.
In web forms I would do something like the code below. What is the best way to handle this in MVC inside the controller? Thanks!
switch (UserSession.AppUserAccessLevel)
{
case AccessLevel.FullAdmin:
txtLastName.Enabled = true;
lnkExportData.Visible = true;
btnSubmit.Enabled = true;
break;
case AccessLevel.Admin:
txtLastName.Enabled = true;
lnkExportData.Visible = false;
btnSubmit.Enabled = false;
break;
case AccessLevel.ReadOnly:
lnkExportData.Visible = false;
btnSubmit.Enabled = false;
break;
}
For doing this in MVC you need to user Model and pass the Model to View through controller. Please find the example code below. You can loop through text boxes and set the property using Razor view.
Controller Action:
public ActionResult YourAction()
{
//Sets your property
string yourProperty = _db.GetProperties().FirstOrDefault();
//Passing in "yourProperty" as the Model to the View
return View(yourProperty);
}
//Alternativately you can bind the property to a Model that has multiple properties
public ActionResult YourAction()
{
YourModelClass model = new Model();
model.Property = _db.GetProperties().FirstOrDefault();
return View(model);
}
Within your View (Top of your View): (The name should match the name of the Controller Action - so YourAction.cshtml / YourAction.aspx)
//You need to firstly bind your Model to a type.
#Model string //This is your first example above. It simply binds the Model to a string
#Model YourModelClass //This binds the Model (and all of its properties) to the passed in YourModelClass
Populating your Textboxes (Again - within your View)
//Now you can access and populate a textbox in the methods previously listed
#Html.TextBox("TextBoxName",Model) //If using a string for the Model
#Html.TextBox("TextBoxName",Model.YourProperty) //If using YourModelClass as the Model
or
#Html.TextBoxFor(model => model.YourProperty) //Again - using YourModelClass
Hi I have my 'home' controller and a 'sort' controller in umbraco 7. The 'home' controller works fine for the index action as it is overridden from RenderMvcController. Firstly I am confused which controller I should using in which instance i.e a surface controller or a rendermvccontroller. I cant seem to access the twitter action below which is something I need for ajax. Do I need to put the twitter action in a surface controller or could I use a regular mvc controller in umbraco?
public override ActionResult Index(RenderModel model)
{
var storedProcedure = new StoredProcedure()
{
ConnectionString = ConfigurationManager.ConnectionStrings["CentralDbContext"].ConnectionString
};
DataSet ds = storedProcedure.ExecuteProcedureToDataSet("GetHomePage");
IMapSetup map = new MapHomePage();
HomePage homepage = map.Setup<HomePage>(ds);
homepage.Slideshow = CurrentPage.AncestorsOrSelf(1).First().Descendants("SlideshowItem").Take(5).AsMany<Slideshow>();
this._weatherSettings.DefaultLocation = "warrington";
homepage.Forecast = new Forecaster(this._weatherSettings, this._cacheHelper).GetWeather(this._weatherSettings.DefaultLocation);
return CurrentTemplate(homepage);
}
public ActionResult TwitterSort(int? page)
{
int currentPageIndex = page.HasValue ? page.Value - 1 : 0;
var storedProcedure = new StoredProcedure()
{
ConnectionString = ConfigurationManager.ConnectionStrings["CentralDbContext"].ConnectionString
};
DataSet ds = storedProcedure.ExecuteProcedureToDataSet("GetHomePage");
IMapSetup map = new MapHomePage();
HomePage homepage = map.Setup<HomePage>(ds);
if (Request.IsAjaxRequest())
{
return PartialView("umbTweets", homepage.Twitter.ToPagedList(currentPageIndex, DefaultPageSize));
}
return PartialView(homepage.Twitter.ToPagedList(currentPageIndex, DefaultPageSize));
}
My Approach is:
Render controller is only for displaying data to user.
Surface controller is for interaction (I use this for interaction mainly ajax, or forms)
For rendering child action you can use following example:
http://our.umbraco.org/documentation/Reference/Mvc/child-actions
Update:
To implement custom routing you can have a look on
http://cpodesign.com/blog/umbraco-implementing-routing-in-mvc/
Partial view does not return any data.When i check with debug tool on PartialView page(_ContentBlock.cshtml), model seem to null.
Controller
public ActionResult Module()
{
int RouteDataValue = default(int);
if (RouteData.Values["id"] != null)
{
RouteDataValue = int.Parse(RouteData.Values["id"].ToString());
}
using (Models.ContentModel db = new Models.ContentModel())
{
var Query = from n in db.PageModule
join m in db.Module on n.ModuleId equals m.ModuleId
where n.PageId == RouteDataValue
select m.PhysicalPath;
return PartialView(Query.Single()); //returns PartialView such as ~/Modules/Content/_ContentBlock.cshtml
}
}
public PartialViewResult ContentBlock()
{
using (Models.ContentModel db = new Models.ContentModel())
{
return PartialView("~/Modules/Content/_ContentBlock.cshtml", db.ContentBlock.Where(n => n.PageId == 2).Single());
}
}
Page.cshtml
#Html.Action("Module")
_ContentBlock.cshtml
#model IEnumerable<Models.ContentBlock>
#foreach (var item in Model)
{
#Html.DisplayFor(n => item.Content)
}
You seem to have used the Html.Partial helper instead of Html.Action. So you were basically only rendering the partial without ever hitting the controller action that is supposed to populate and the model to the partial.
Your page Page.cshtml is calling the partial view action Module using:
#Html.Action("Module")
The action called Module is being executed. In that action, your query results in a path to your view, such as:
"~/Modules/Content/_ContentBlock.cshtml"
That action is returning the single result of that query using:
return PartialView(Query.Single());
What this is doing is passing the name of the view to the PartialView method to return which view is going to be used to display data from the action. In addition, no model data is included in this return.
That's where your problem is. When you return the path to the partial view, you are simply telling the MVC system what view to use to display the data from Module. It won't actually call another partial view. That's not how it works. So your model is null because, you didn't pass any data in your PartialView(...) call.
You have another action called ContentBlock. But that action is not being called because nothing is calling it.
Edit:
Another problem you have is that _ContentBlock.cshtml uses a model of IEnumerable<ContentBlock>, but you're only passing it a .Single() from your ContentBlock action.
I have one action has these attributes:
[OutputCache(Location = System.Web.UI.OutputCacheLocation.Server, Duration = 300, VaryByParam = "*")]
and another with
[OutputCache(Location = System.Web.UI.OutputCacheLocation.None)]
and they both use the same View.
In the View, or even in the Action Method, how to I determine what the caching is? i.e. is it a cached page or not? I've tried looking at Response.Headers (only has "Server: Microsoft-IIS/7.0), & Response.CacheControl is "private" in both cases.
I haven't used this in the application, but for the sake of seeing if it's possible, I've done this sample... using Reflection, and a base controller, and calling Initialize() from my action method, the following code gets the OutputCache attributes from the calling method. Then a View or Partial View can get the cache location from the ViewBag.
public class BaseController : Controller
{
public void Initialize()
{
var stackTrace = new StackTrace();
if (stackTrace.FrameCount >= 1)
{
var methodBase = stackTrace.GetFrame(1).GetMethod();
var filters = (OutputCacheAttribute[])methodBase.GetCustomAttributes(typeof(OutputCacheAttribute), false);
if (filters.Length > 0)
{
ViewBag.CacheLocation = filters[0].Location;
}
}
}
}