I was wondering what, if it is possible, is the best way to render a partial using the new razor view engine. I understand this is something that wasn't finished completely by the time
Right now I am using RenderPage to render the user control:
#RenderPage("~/Views/Shared/LocaleUserControl.cshtml",ViewData.Model)
The page calling RenderPage uses a layout (master) page with three sections defined: TitleContent, HeadContent and Maincontent. When I attempt to render my locale control from this page it appears that these sections are also required - they should only be required in the calling page and are present. I receive the following message, regardless of whether or not I include the sections in my partial view (obviously I dont want to include these sections but it seemed like an interesting debugging point...).
The following sections have been
defined but have not been rendered on
the layout page
'~/Views/Shared/LocaleUserControl.cshtml':
TitleContent; HeadContent; MainContent
My partial view is as follows (adapted from the following link):
#inherits System.Web.Mvc.WebViewPage<LocaleBaseModel>
#using System.Web.UI;
<p>
#Html.LabelFor(model => Model.CountryName)
<br />
#Html.DropDownListFor(model => Model.CountryName,null, string.Empty, new { #class = "text", accesskey="u"})
</p>
<p>
#Html.LabelFor(model => Model.StateProvince)
<br />
#Html.DropDownListFor(model => Model.StateProvince, null, string.Empty, new { #class = "text", accesskey="t" })
</p>
<script type="text/javascript">
$(function () {
var countries = $("#CountryName");
var statesprovinces = $("#StateProvince");
countries.change(function () {
statesprovinces.find('option').remove();
var url = '#Url.Action("GetStatesProvinces", "Base")';
$.getJSON(url, { countryId: countries.val() }, function (data) {
$(data).each(function () {
$("<option value=" + this.ID + ">" + this.Name + "</option>").appendTo(statesprovinces);
});
});
});
});
</script>
You partial looks much like an editor template so you could include it as such (assuming of course that your partial is placed in the ~/views/controllername/EditorTemplates subfolder):
#Html.EditorFor(model => model.SomePropertyOfTypeLocaleBaseModel)
Or if this is not the case simply:
#Html.Partial("nameOfPartial", Model)
If you don't want to duplicate code, and like me you just want to show stats, in your view model, you could just pass in the models you want to get data from like so:
public class GameViewModel
{
public virtual Ship Ship { get; set; }
public virtual GamePlayer GamePlayer { get; set; }
}
Then, in your controller just run your queries on the respective models, pass them to the view model and return it, example:
GameViewModel PlayerStats = new GameViewModel();
GamePlayer currentPlayer = (from c in db.GamePlayer [more queries]).FirstOrDefault();
[code to check if results]
//pass current player into custom view model
PlayerStats.GamePlayer = currentPlayer;
Like I said, you should only really do this if you want to display stats from the relevant tables, and there's no other part of the CRUD process happening, for security reasons other people have mentioned above.
Related
I have several views with different viewmodels.
Every view has "ProjectId" dropdownlist, and I want to show selected project's start date beside the "ProjectId" dropdownlist before submit.
And the "ProjectId" dropdownlist is a ViewBag.
Is there any other way besides adding start date to each viewmodel?
view:
<div class="form-inline">
Project:
<div>
#Html.DropDownList("ProjectId", new SelectList(ViewBag.ProjectsDropDownList, "Value", "Text"))
</div>
</div>
It is a bit hard to answer you without you supplying your code but I have had a look at
https://www.tutorialsteacher.com/mvc/viewbag-in-asp.net-mvc regarding viewbags which you are welcome to have a look at.
It shows that you could simply use a label with something like this in the front end:
<label>Project Start Date:</label> #ViewBag.projectStartDate
That would be if you are using ASP.NET or HTML for the client side coding
In the back end something like this :
namespace MVC_BasicTutorials.Controllers
{
public class ProjectController : Controller
{
string projectName;
int projectId;
string projectDate;
public ProjectController ()
{
projectName = "new project";
projectId = 0;
projectDate = "01-01-1990";
}
public ActionResult returnDate()
{
ViewBag.projectStartDate = this.projectDate;
return View();
}
}
}
The last approach I used:
ProjectsController:
public PartialViewResult ProjectDate(int projectId)
{
// get project start date
ViewBag.StartDate = startDate;
return PartialView("_ProjectDate");
}
_ProjectDate.cshtml:
// use ViewBag.StartDate to render html what I want
get_start_date.js
$(document).ready(function () {
var projectId = $('#ProjectId').val();
if (projectId != undefined) {
$.ajax({
url: '/Projects/GetProjectDate',
data: { ProjectId: projectId },
success: function (result) {
$("#project_date").html(result);
}
});
}});
_Layout.cshtml import get_start_date.js, and insert this code in the page I need:
<div id="project_date"></div>
I'm unsure if this is possible but I want to use jQuery to assign value from my bound model to different textboxes inside a PartialView.
Originally when the page loads, it populates correctly with all of the model information. However I would like to implement a DDL to view historical updates (retrieved from my pre-populated DB).
I am able to call an Action method inside my respective controller which accepts a revisionID. I have verified that the method is returning the correct data.
Please see below for my code snippets:
Partial View:
$('#revisionDDL').change(function () {
var selectedRevisionID = $(this).val();
if (selectedRevisionID == '') {
selectedRevisionID = #Model.RevisionID - 1;
}
var url = '#Url.Action("GetAgreementByRevision")';
$.get(url, { revisionID: selectedRevisionID }, function () {
$('#ChangeReason').val('#Model.ChangeReason');
})
});
Input element:
<div class="input-group">
<span class="input-group-addon" id="change-reason">Change Reason</span>
#Html.TextAreaFor(m => m.ChangeReason, new { #class = "form-control", #rows = "1" })
</div>
Controller method:
public ActionResult GetAgreementByRevision(int revisionID)
{
Agreement revisedAgreement = new Agreement();
revisedAgreement = _agreementService.GetAgreementDetailsByRevision(revisionID);
return PartialView("AgreementDetailsFormPartial", revisedAgreement);
}
If I am not able to accomplish this, what would be my other options?
Your method in the controller returns PartialView which returns HTML content and you're trying to pass that HTML content as a value in the text area - this is not how it should work. You should return Json(revisedAgreement, JsonRequestBehavior.AllowGet); and then access this object in JavaScript.
$.get(url, { revisionID: selectedRevisionID }, function (data) {
// 'data' is your Agreement object
$('#ChangeReason').val(data.SomePropertyHere);
});
I am working on my third year project and I'm struggling with this one section so badly, I have looked around and found some answers but I really done know how to implement in my code because it always just doesn't work. So I don't know what I'm doing wrong.
What i would like is for the partial view to change when the drop down selected item has changed.
This is what was generated in the view for this section.
<div class="form-group">
#Html.LabelFor(model => model.TypeID, "TypeID", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("TypeID", String.Empty)
#Html.ValidationMessageFor(model => model.TypeID)
</div>
</div>
Most solutions I have seen use a #html.dropdownlistfor().
Any help would be appreciated even if you could just point me to the right place.
The drop down list is filled from the database relationships.
I have got this to work if i use labels in an "a" tag with an href but they are hard coded onto the page. I want to use the drop down list so that if i update the database it will have the updated list instead of me going to change it in the code, its also more user friendly in my eyes.
Thanx in advance
You could retrieve the data from the server and construct/change the DOM via JQuery, or you could use a partial view that is appropriate for each question type, attaching an event handler to the change event of the drop-down via JQuery.
One approach, loading partial views:
yourNamespace.yourScript.js file (include the file in your main view via the <script> tag with the src attribute):
(function ($) {
if (!window.yourNamespace) {
window.yourNamespace = {};
}
if (!window.yourNamespace.yourPageScript) {
window.yourNamespace.yourPageScript = function () {
var populateView = function (dropDown) {
if (dropDown && dropDown.length) {
var value = dropdown.val();
$.ajax({
method: "GET",
cache: false,
url: "some.url/PopulateType",
dataType: "HTML"
data: { selectedValue: value }
})
.done(function (response) { // jQuery 1.8 deprecates success() callback
var div = $('#partialViewDiv');
div.html('');
div.html(response);
});
}
};
return {
populateView: populateView
};
};
}
}(jQuery));
Your main view could have something like this:
<script type="text/javascript">
// put the script section somewhere appropriate in the page
$(document).ready(function () {
var dropDown = $('#TypeId'); // assuming the ID of this element is 'TypeId'
dropDown.change(function () {
yourNamespace.yourPageScript.populateView(dropDown);
});
});
</script>
<div id="partialViewDiv">
#Html.RenderPartial("path to initial partial view", model);
</div>
partial view example (adjust to be proper for any particular dropdown selection):
#model namespaceName.QuestionTypeModel
<div class="form-group>
#* put controls appropriate to the particular partial views here, such as radio buttons for the multiple choice question type, etc. *#
<div>
<div class="form-group">
#Html.LabelFor(model => model.TypeID, "TypeID", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("TypeID", Model.QuestionTypeValues)
#Html.ValidationMessageFor(model => model.TypeID)
</div>
</div>
Part of the controller:
[HttpGet]
public ActionResult Index()
{
var model = new MainViewModel();
// populate the model with data here for the initial display, including the initial drop-down values,
// presumably the same way you do now
// into model.QuestionTypeValues
return View(model); // the main view
}
[HttpGet]
public ActionResult PopulateType(int selectedValue) // could use an enum for the selectable values
{
var model = new QuestionViewModel();
string partialViewName = null;
// populate with data appropriate to the partial views
switch (selectedValue)
{
case 0:
partialViewName = "partial view name for item 0";
// populate "model" with the appropriate data
break;
case 1:
partialViewName = "partial view name for item 1";
// populate "model" with the appropriate data
break;
// and so on...
default:
throw new ArgumentException("unknown selected value", "selectedValue");
break;
}
return PartialView(partialViewName, model);
}
The approach to use jQuery to build the DOM elements instead of using partial views is left as an exercise.
I have one layout and one partial view which are in the Shared folder. Partial view presents top menu items which are not static. So I need to call an action method to get menu items from database. To do this, I created a controller and add an action method in it.
When I try to browse the page in web browser, this error occured:
The controller for path '/' was not found or does not implement IController.
Note:
I tried Html.RenderAction, Html.Partial methods too...
And I tried to create another view folder, and create a new partial view and new controller that named with "folder name + Controller" suffix.
Layout:
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
</head>
<body>
<div id="header">
#Html.Action("~/Views/Shared/_TopMenu.cshtml", "LayoutController", new {area =""}); //Here is the problem.
</div>
<div>
#RenderBody();
</div>
</body>
</html>
_TopMenu.cshtml:
#model IList<string>
#foreach (string item in Model)
{
<span>item</span>
}
LayoutController (in Controllers folder):
public class LayoutController : Controller
{
//
// GET: /Shared/
public ActionResult Index()
{
return View();
}
[ChildActionOnly]
[ActionName("_TopMenu")]
public ActionResult TopMenu()
{
IList<string> menuModel = GetFromDb();
return PartialView("_TopMenu", menuModel);
}
}
What happens if you put this in your view?
#{ Html.RenderAction("TopMenu", "Layout"); }
(And comment this out until everything works: //[ChildActionOnly])
Change this line,
#Html.Action("~/Views/Shared/_TopMenu.cshtml", "LayoutController", new {area =""});
to,
#Html.Action("_TopMenu", "Layout", new {area =""});
and check.
exist differents ways, for this case I like use html.action in layout, and in control I will create a string Menu, the string contains the html code I need, the controller end with return Content(menu);
for example
Layout:
<body>
<nav>
#Html.Action("_TopMenu", "Layout")
</nav>
the controller
public class LayoutController : Controller
{
public ActionResult _TopMenu()
{
IList<string> menuModel = GetFromDb();
string menu = "<ul>";
foreach(string x in menuModel)
{
menu +="<li><a href='"+x+"'>+x+"</a></li>";
}
menu+="</ul>";
return Content(menu);
}
}
I like that because I can use many options to create menus dinamics more complexes.
other way use ajax to recovered the data and use handlebars or other template for the code
You are using the wrong overload of the Action-Method. The 2nd parameter in the variation is not the controllername but the actionname.
You can check the correct Method overloads on this page
Also: If you specify Controllers in the Html.Action Method (which you can do for example with this variation of the Method), you dont need to write the suffix "Controller" even if thats your Classname. So Instead of using the string "LayoutController" you would write simply "Layout".
At this point the framework is convention-based.
This is how I did it:
Layout
#Html.Action("GetAdminMenu", "AdminMenu")
Admin Menu Controller
public PartialViewResult GetAdminMenu()
{
var model = new AdminMenuViewModel();
return PartialView(model);
}
GetAdminMenu.cshtml
#model ReportingPortal.Models.AdminMenuViewModel
<div class="form-group">
<label class="col-md-4 control-label" for="selectbasic">School Name</label>
<div class="col-md-8">
#Html.DropDownListFor(model => model.SelectedID, new SelectList(Model.DataList, "Value", "Text", Model.SelectedID), "", new { #class = "form-control", #required = "*" })
</div>
</div>
Currently I have a main view that contains a KendoGrid. Based on a button the user clicks, we see the context and display a partial view according to the row clicked (The row could be of phone, address or electronic type). I am loading the partial view via an AJAX call like mentioned in this answer (Render Partial View Using jQuery in ASP.NET MVC).
The following is the javascript to load the form :
function LoadEditPage(x) {
var grid = $("#contactGrid").data("kendoGrid");
var Id = grid.dataItem(x.parent().parent()).ContactId;
var Type = grid.dataItem(x.parent().parent()).ContactType;
$.get("ShowEditForm", { Id: Id, Type: Type }, function(data) {
$("#EditForm").html(data);
});
}
The following is the action that handles the request for partial View :
public ActionResult ShowEditForm(int Id, string Type)
{
var clientChannel = new ClientChannel<IContactManger>("clientEndPoint1");
var getContactByPartyIdResponse = clientChannel.Channel.GetContactByPartyID(1);
switch (Type)
{
case "Address" :
var address = getContactByPartyIdResponse.Contact.AddressDto.FirstOrDefault(x => x.ContactId == Id);
return PartialView("_Address", address);
break;
case "Telephone" :
var telephone = getContactByPartyIdResponse.Contact.PhoneDto.FirstOrDefault(x => x.CNTCT_ID == Id);
return PartialView("_Telephone", telephone);
break;
case "Electronic" :
var electronic = getContactByPartyIdResponse.Contact.ElectronicDto.FirstOrDefault(x => x.CNTCT_ID == Id);
return PartialView("_Electronic", electronic);
break;
}
return null;
}
address, telephone and electronic are three different types of classes and are passed to three separate partial views.
The following is an example of a partial view called _Telephone:
#model KY.COT.DS.Common.CManager.Services.DataContracts.DTO.Telephone
#using (Html.BeginForm())
{
<div>
#Html.LabelFor(m => m.AREA_CD)
#Html.TextBoxFor(m => m.AREA_CD)
#Html.ValidationMessageFor(m => m.AREA_CD)
</div>
<div>
#Html.LabelFor(m => m.LN_NMBR)
#Html.TextBoxFor(m => m.LN_NMBR)
#Html.ValidationMessageFor(m => m.LN_NMBR)
</div>
<div>
#Html.LabelFor(m => m.EXTNSN)
#Html.TextBoxFor(m => m.EXTNSN)
#Html.ValidationMessageFor(m => m.EXTNSN)
</div>
<input type="submit" value="Submit"/>
}
The problem I have is that when we make edits to the form and submit it, I don't know how I should set it up such that the form returns with appropriate validation messages without making changes to the main page we currently are on. I only want the partial view to update, while keeping the main view the same.
I have seen this question a couple of more places, but they have no answers. I would really appreciate it if someone could shed some light on this problem or if there are alternate strategies. Thanks in advance!