ASP MVC 3 create Partial View or Custom Helper with params - asp.net-mvc-3

I am very new to asp.mvc 3. I am using kendoui and knockout for binding. My application looks like this sample:
ViewModel
public class MyViewModel
{
public MyViewModel()
{
Initialize();
}
public IEnumerable<string> MyOptions1 { get; set; }
public string MyChoice1 { get; set; }
public IEnumerable<string> MyOptions2 { get; set; }
public string MyChoice2 { get; set; }
private void Initialize()
{
MyOptions1 = new List<string>()
{
"OptionA",
"OptionB"
};
MyOptions2 = new List<string>()
{
"OptionC",
"OptionD"
};
}
}
Index method of Home controller
public ActionResult Index()
{
return View();
}
Index View:
<div id="optionsArea">
<table>
<tr>
<td><label>Option1:</label></td>
<td><input id="options1" data-bind="kendoDropDownList: { data: MyOptions1, value: MyChoice1 }" /></td>
</tr>
<tr>
<td><label>Option2:</label></td>
<td><input id="options2" data-bind="kendoDropDownList: { data: MyOptions2, value: MyChoice2 }" /></td>
</tr>
</table>
</div>
When Index view is loaded I am calling OptionsData method of controller which returns the populated MyViewModel as Json.
public ActionResult OptionsData()
{
var myModel = new MyViewModel();
var jsonNetResult = new JsonNetResult
{
Formatting = Formatting.Indented,
Data = myModel
};
return jsonNetResult;
}
In javascript From MyViewModel I create populated javascript viewmodel viewModel with knockout observable properties and bind it to the div in the Index View.
$(function () {
my = {
}
$.getJSON("/Home/OptionsData", function (data) {
// create observable properties from MyViewModel
my.viewModel = ko.mapping.fromJS(data);
ko.applyBindings(my.viewModel, document.getElementById("optionsArea"));
});
});
In my application I have many elements containing label and dropdown so I want to extract that part in something like a component and reuse it calling it with some parameters to replace the bindings. I read some articles and maybe the solution is to use partial views or custom HTML helpers so I can do something like this:
_OptionPartialView
<tr>
<td><label>Option2:</label></td>
<td><input data-bind="kendoDropDownList: { data: (parameter1), value: (parameter2) }" /></td>
</tr>
where somehow I want to replace parameter1 and parameter 2 when I call the partial in the Index View:
#Html.Partial("_OptionPartialView.cshtml", parameter1, parameter2);
or with helper method:
#Html.MyCustomHelper(..., parameter1, parameter2);
Then I will strongly bind my Index method to the Index view:
public ActionResult Index()
{
var myModel = new MyViewModel();
return View(myModel);
}
And my view will look something like this:
#model MVC3Question.Models.MyViewModel
<div id="optionsArea">
<table>
#Html.Partial("_OptionPartialView.cshtml", Model.MyOptions1, Model.MyChoice1);
#Html.Partial("_OptionPartialView.cshtml", Model.MyOptions2, Model.MyChoice2);
</table>
</div>
My question is which is better in this situation Partial View or Custom Helper method and more important how do I implement them with the parameters having in mind the posted sample code. Any other approches or ideas are welcome. Thanks!

In my opinion both methods are good.
You can create a custom helper that takes two parameters like this:
public static MvcHtmlString MyHtmlHelper(this HtmlHelper htmlHelper, string label, IEnumerable<string> option, string choise)
{
var html = new MvcHtmlString(String.Empty);
html = MvcHtmlString.Create("<tr><td><label>" + label + ":</label></td><td><input data-bind=\"kendoDropDownList: { data: (" + option + "), value: (" + choise + ") }\" /></td></tr>");
return html;
}
I would prefer this method because it will work without any change in your current code.
If you want to use a partial view you will need to change your current model.
public class MyViewModel
{
public MyViewModel()
{
MyOptions = new List<string();
}
public IEnumerable<string> MyOptions { get; set; }
public string MyChoice { get; set; }
}
Then you can populate the model in your controller like this:
public ActionResult Index()
{
var viewModels = new List<MyViewModel>();
var myOptions1 = new List<string>()
{
"OptionA",
"OptionB"
};
var myOptions2 = new List<string>()
{
"OptionC",
"OptionD"
};
viewModels.Add(new MyViewModel{MyOptions = myOptions1});
viewModels.Add(new MyViewModel{MyOptions = myOptions2});
return View(viewModels);
}
After that you need to change your view like this:
#model IList<MVC3Question.Models.MyViewModel>
<div id="optionsArea">
<table>
#foreach(var viewModel in Model)
{
#Html.Partial("_OptionPartialView.cshtml", viewModel);
}
</table>
</div>
And finally create a partial view:
#model Mvc3Question.Models.MyViewModel
<tr>
<td><label>Option2:</label></td>
<td><input data-bind="kendoDropDownList: { data: (#Model.MyOptions), value: (#Model.MyChoice) }" /></td>
</tr>
I hope this helps.

Related

Ajax WebGrid Paging MVC3

I'm using WebGrid and I need to switch between pages with Ajax.
Index Code
<script src="../../Scripts/jquery.unobtrusive-ajax.js" type="text/javascript"></script>
<script src="../../Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
#using (Ajax.BeginForm("GetGrid", new AjaxOptions() { UpdateTargetId = "Res" }))
{
<input type="text" />
<input type="submit" value="start" />
<div id="Res">
</div>
}
Result partial view
#model IEnumerable<MvcApplication1.Controllers.Model>
<div id="grid2">
#{
var grid = new WebGrid(source:Model,rowsPerPage:6,ajaxUpdateContainerId: "grid2");
#grid.GetHtml(htmlAttributes: new { id = "grid2" },
columns: grid.Columns(
grid.Column("Someting")
));
}
</div>
Controller Code
public class ABCController : Controller
{
//
// GET: /ABC/
public ActionResult Index()
{
return View();
}
public static List<Model> mo = new List<Model>();
[HttpPost]
public ActionResult GetGrid()
{
for (int i = 0; i < 1000; i++)
{
mo.Add(new Model() { Someting = i.ToString() });
}
return PartialView("Result", mo);
}
}
public class Model
{
public string Someting { get; set; }
}
This work for first page but nothing happens for other pages.
After some hours i could not find some thing that help me.i noticed to html code of my page links.
page link
2
so i finally got how it's work.i add an ActioResult to my controller like this:
[HttpGet]
public ActionResult GetGrid(int page)
{
return PartialView("Result",mo);
}
and worked.i hope this be helpfull for some one

How to send Model value as parameter while submitting #Ajax.Beginform()

I am using #Ajax.Beginform in my View which is tightly bound to the ViewModel.
I've #Html.ListBoxFor inside my form. I add and delete items from the listbox using jQuery. Now what I am want to achieve is that onpress of the submit button, it should send full data present in the listbox regardless of which are selected. Currently it sends the list to controller if I select all the item in the listbox and press submit button. But I don't want to do that. Any idea as to how to achieve this?
Can it be sent as a form parameter.
#using (Ajax.BeginForm("SaveTextComponent", "LoanFilterEditor", new{ param1 = Model.listBoxItem}, new AjaxOptions { HttpMethod = "POST", OnSuccess = "SUCCESS" }))
I try to accept the parameter in the controller like this
public ActionResult SaveTextComponent(TextComponentViewModel model, List<SelectListItem> list)
{
}
But list is null.. Please help.
Maybe you can use this javascript to select all items at your listbox and then, send it to controller:
function listbox_selectall(listID, isSelect) {
var listbox = document.getElementById(listID);
for(var count=0; count < listbox.options.length; count++) {
listbox.options[count].selected = isSelect;
}
}
And after that, you can call the function on your form in this way:
<script>
function submit() {
listbox_selectall('righthand_side_listbox_id', true);
return true;
}
</script>
<form onsubmit="return submit()">
...
</form>
Credits to Viral Patel blog
You can follow my example:
Model:
pulic class TextComponentViewModel {
public int[] SelectedListItem { get; set; }
public List<Item> ListItem { get; set; }
}
public class Item {
public int Id { get; set; }
public String Name { get; set; }
}
View:
#model TextComponentViewModel
#using (Ajax.BeginForm("SaveTextComponent", "LoanFilterEditor", null, new AjaxOptions { HttpMethod = "POST", OnSuccess = "SUCCESS" }, new {name = "mainForm", id = "mainForm"}))
{
#Html.ListBoxFor(model => model.SelectedListItem , new MultiSelectList(Model.ListItem, "ID", "Name"))
for(var i = 0; i < Model.ListItem.Count();i++ )
{
#Html.HiddenFor(m => m.ListItem[i].Id)
#Html.HiddenFor(m => m.ListItem[i].Name)
}
<input type = "submit" id="submitButton" />
}
Controller:
public ActionResult SaveTextComponent(TextComponentViewModel model)
{
}
Script:
$("#submitButton").click(function(){
$("#mainForm").submit();
});

Ajax paged list pass object to controller

I am working on some advanced searching functionality and I have run into a roadblock. I would like to use AJAX for my search results and use the PagedList additons to handle paging. I have an AdvancedSearchResults action which takes a search filters class and the current page. The issue is how can I pass the search Filters class into this action correctly. I am sure something I am doing just isnt organized correctly as I would think this would be fairly common. I would really appreciate any help. Thanks in advance.
Controller Action:
public ActionResult AdvancedSearchResults(AdvancedSearchFilters searchFilters, int ? page)
{
//DO STUFF
return PartialView("_SearchResults", results);
}
AdvancedSearchResults Filters:
public class AdvancedSearchFilters
{
public string SearchText { get; set; }
public List<string> SelectedTableTypes { get; set; }
public List<Guid> SelectedGenreIds { get; set; }
public List<Guid> SelectedPlatformIds { get; set; }
public int YearMax { get; set; }
public int YearMin { get; set; }
public int RatingMin { get; set; }
public int RatingMax { get; set; }
}
Search Results Partial View:
#model List<SearchResultItem>
#using PagedList
#using PagedList.Mvc
<!-- 15 Per Page -->
<h2>Search Results</h2>
#if (ViewBag.OnePageOfSearchItems.Count > 0)
{
<div class="pagination">
#Html.PagedListPager((IPagedList)ViewBag.OnePageOfSearchItems, page => Url.Action("AdvancedSearchResults", "Search", new { searchFilters = ViewBag.AdvancedSearchFilters, page = page }),
PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(PagedListRenderOptions.OnlyShowFivePagesAtATime, "#main-results"))
</div>
foreach (var searchResultItem in Model)
{
<a href="#Url.Action(searchResultItem.ResultType, searchResultItem.ResultType, new { id = searchResultItem.ResultId })" class="result">
#if (searchResultItem.ProfileImageLocation != null)
{
<img src="#searchResultItem.ProfileImageLocation" alt="#searchResultItem.ResultName" />
}
<div class="result-info">
<h3>#searchResultItem.ResultName</h3>
<p>#searchResultItem.DisplayText</p>
</div>
</a>
}
<div class="pagination">
#Html.PagedListPager((IPagedList)ViewBag.OnePageOfSearchItems, page => Url.Action("AdvancedSearchResults", "Search", new { searchFilters = ViewBag.AdvancedSearchFilters , page = page }),
PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(PagedListRenderOptions.OnlyShowFivePagesAtATime, "#main-results"))
</div>
}
else
{
<span>No Matches.</span>
}
Try passing the data to action method in the form of json. Try the below code which pass the json object to action method.
//// construct your json object.
var jsonObj = '{"SelectedTableTypes" : [{"1","2"}]}';
var postData = $.parseJSON(jsonObj);
$.ajax(
{
url: // your URL with Action name AdvancedSearchResults,
data: postData,
cache: false,
dataType: "json",
success: function (result) {
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
});

Cascading Dropdown in Mvc3

I am using Mvc3 I have 2 dropdown,BankBranch and city.
On first time load of view i am binding both the dropdon without cascading. then if user select city i want to change bankbranch according to that.
I am confused how i can achieve both the things together.
Thanks in advance.
This blog post should get you on your way. It provides examples for normal form posts, microsoft ajax form post, jquery ajax and others.
http://weblogs.asp.net/raduenuca/archive/2011/03/06/asp-net-mvc-cascading-dropdown-lists-tutorial-part-1-defining-the-problem-and-the-context.aspx
EDIT:
Generalized Code Explanation
Model
public class CascadeModel {
public SelectList<City> Cities { get; set; }
public SelectList<BankBranch> BankBranches { get; set;}
public int CityId { get; set; }
public int BranchId { get; set; }
}
public class Branch {
public int Id { get; set;}
public string Name { get; set; }
}
Controller:
public ActionResult BranchSelector() {
var viewData = new CascadeModel();
viewData.Cities = new SelectList(Repository.GetAllCities(), "Id", "Name", selectedCity);
viewData.BankBranches = new SelectList(Repository.GetBranchesByCity(selectedCity), "Id", "Name", "");
return View(viewData);
}
public JsonResult GetBranches(int id) {
return Json(Repository.GetBranchesByCity(id), JsonRequestBehavior.AllowGet);
}
View:
#model CascadeModel
#Html.DropDownListFor(m => m.CityId, Model.Cities, new { style = "width:250px" })
<br />
#Html.DropDownListFor(m => m.BranchId, Model.BankBranches, new { style = "width:250px" })
<script type="text/javascript">
$(document).ready(function() {
$("#CityId").bind('change', function() {
$.ajax({
url: '/Controller/GetBranches/' + $(this).val(),
success: function(data) {
//Clear the current branch ddl
//Load the new Branch data returned from the jquery call in the branches ddl
}
});
};
});
</script>

Master-Detail Sample Code for MVC 3 Razor (using Ajax for details)

I am looking for sample code to create a master/details with c# mvc 3.
Specifically, I am trying to figure out how to call via ajax the rendering of a partial view. I am able to put the partial view on the form but want to populate it after a user has selected an item from a select list via ajax.
thx
As always you start with the model:
public class MyViewModel
{
public int Id { get; set; }
public string Title { get; set; }
}
public class DetailsViewModel
{
public string Foo { get; set; }
public string Bar { get; set; }
}
then a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
// TODO: don't hardcode, fetch from repository
var model = Enumerable.Range(1, 10).Select(x => new MyViewModel
{
Id = x,
Title = "item " + x
});
return View(model);
}
public ActionResult Details(int id)
{
// TODO: don't hardcode, fetch from repository
var model = new DetailsViewModel
{
Foo = "foo detail " + id,
Bar = "bar detail " + id
};
return PartialView(model);
}
}
and corresponding views.
~/Views/Home/Index.cshtml:
#model IEnumerable<MyViewModel>
<ul>
#Html.DisplayForModel()
</ul>
<div id="details"></div>
<script type="text/javascript">
$(function () {
$('.detailsLink').click(function () {
$('#details').load(this.href);
return false;
});
});
</script>
~/Views/Home/Details.cshtml:
#model DetailsViewModel
#Model.Foo
#Model.Bar
~/Views/Home/DisplayTemplates/MyViewModel.cshtml:
#model MyViewModel
<li>
#Html.ActionLink(Model.Title, "details", new { id = Model.Id }, new { #class = "detailsLink" })
</li>
I have blogged about creating master detail form using asp.net mvc where you can add n child records on clietn side without the need of sending ajax request just to bring the editor fields for child records. it used jquery templates

Resources