Accessing model data, from MVC3 partial view, in controller without passing it explicitly in the view - asp.net-mvc-3

I have a MVC3 partial view that is called with a model.
#model SomeModel
The model have an Id parameter.
In the view I call #Html.Action("SomeMethod", "SomeController")
Is there any way to access the Id parameter in the SomeMethod ActionResult without passing it explicitly like this:
#Html.Action("SomeMethod", "SomeController", new {"Id" = Model.Id})
The problem is that I can not change the source code of the partial view. And I need the Id value. The Id is not used in the partial view so I can not access it via JavaScript.
Is the model passed to the HttpContext and is there any way to pass it?
EDIT: The thing is that I am developing a plugin for nopCommerce, like the ones that are offered by nop-templates. nopCommerce is an open source software and I can change the code, but the plugin will be shipped separately, so it is not recommended to make changes in nopCommerce views and the view that I am referring to is such.

When you can't change the sourcecode of the partial view, there is no way of getting to the id value in your controller. Its completely decoupled as thats one major point of the MVC pattern.
You have to explicitely pass it as a parameter to your action.
A dirty workaround might be to store that id somewhere in the Session.

In my project i fill my state drop down list by country id like this
in my view
i pass country id to my controller ActionResult like this
<script type="text/javascript">
function cascadingdropdown() {
var countryID = $('#countryID').val();
$.ajax({
url: "#Url.Content("~/City/State")",
dataType: 'json',
data: { countryId: countryID },
success: function (data) {
alert(data);
$("#stateID").empty();
$("#stateID").append("<option value='0'>--Select State--</option>");
$.each(data, function (index, optiondata) {
alert(optiondata.StateName);
$("#stateID").append("<option value='" + optiondata.ID + "'>" + optiondata.StateName + "</option>");
});
},
error: function () {
alert('Faild To Retrieve states.');
}
});
}
</script>
in my controller i have action
public JsonResult State(int countryId)
{
var stateList = CityRepository.GetList(countryId);
return Json(stateList, JsonRequestBehavior.AllowGet);
}
i think this will help you ....

Related

How to show the view of method in controller when data passed from ajax in ASP.NET MVC

I am developing MVC application.
I want pass the values from View to controller.
I have use ajax to pass the values from View to controller.
Now this data goes perfectly into method....
$(document).ready(function () {
$('#CheckOrder').click(function(){
PassData();
});
function PassData()
{
$.ajax({
url: '#Url.Action("ShowWHOrder", "Order")',
type: 'POST',
data: { OrderNo: #ViewBag.OrderNo, OrderTo : '#ViewBag.OrderTo' }
});
}
});
Here is the method... in below method all parameters comes properly.
[HttpPost]
public ActionResult ShowWHOrder(string OrderNo, string OrderTo)
{
ViewBag.OrderNo = OrderNo;
ViewBag.OrderTo = OrderTo;
return View();
}
Now, I have added the new view for this method.
But It doesn't redirect to new view, it remains on previous view only.
Is due to ajax ?
What option I have to show the new view ?
How can I implement this without ajax ?

How To Correctly Use the HTML.DropDownList with Ajax Calls for MVC

I populated a SelectList Programmatically using the SelectList Constructor (IEnumerable, String, String)
IEnumerable<Permission> ie_SelLstContentAvailPerms;
tmpLstPermissions = FilterAssignablePermissionsByRoleMgblty(p_iRoleId,vmRolePermAdmin.lstPermissionsSource);
//test Forcing Results in to IEnumerable format for Select list Constructor
ie_SelLstContentAvailPerms = tmpLstPermissions.ToList();
vmRolePermAdmin.selLstPermissionsSource = new SelectList(ie_SelLstContentAvailPerms, "PermissionId", "Name");
And I use the DropDownList structure :
#Html.DropDownList("ddlAssignedRolePermissions", (Model.selLstCurrentRolePermissions), null, new { #id = "ddlAssignedRolePermissions", #size = "5", #onchange = "ddlAssignedRolePermissionsEvent(this)" })
My previous use of this structure has an ajax call who's success method is returning the updated model ----but its main body(Postify to AssignPermission(iUserID))is doing the work to the viewmodel based upon the item selected in the drop down list
$.ajax({
url: "~/../../User/AssignPermission",
type: "POST",
data: $.postify({ "p_permId": optionSelectedPerm.value, "p_UserId": iUserId }),
cache: false,
success: function () {
ReloadUserPermissions();
},
error: function () {
// alert("FAIL"); //TODO ?
}
});
I was attempting to replicate this structure for a new page , but instead of using the success results method of the Ajax call I've been trying to return the updated model in the main ajax work.. if the above example were structured this way there would be no success function and the controller ActionResult method would return the updated model. This isnt working . I see the data (updated) in the view while debugging but it does not up date the view ...
Do I have to use the success function of the Ajax call in order to update the view?
<script type="text/javascript">
$(document).ready(function () {
var optionSelectedPerm;
var mvcTmpData_iCurrentRoleID;
});
function SelectedRole(p_lstRole) {
debugger;
mvcTmpData_iCurrentRoleID = $("#ddlSelectedRole").val();
$.ajax({
url: "~/../../AdminRoles/AdminRolePermissions",
type: "POST",
data: $.postify({ "p_nullRoleId": mvcTmpData_iCurrentRoleID }),
cache: false,
success: function () {
AjaxReloadRolePermissions();
},
error: function () {
},
});
function AjaxReloadRolePermissions() {
//alert("Current RoleID: " + mvcTmpData_iCurrentRoleID);
var url = '#Url.Action("ReloadRolePermissions", "AdminRoles", new { p_RoleId = "zReplaceRoleId" })';
window.location.href = url.replace('zReplaceRoleId', mvcTmpData_iCurrentRoleID);
}
}
</script>
Please note that in order to accomplish the first working scenario the controller method as cited in the Ajax call "AssignPermission" is an ActionResult of Type EmptyResult and marked [HttpPost] so basically it can do work and not worry about a real return. BUT !! the Success function of this same Ajax call allows me to update the view with the newly adjusted ViewModel....
My atempt to reproduce my original results is failing I see the model content but it doesnt render in the view
If anyone cares its pretty simple the Ajax function's main work cant call a controller action that updates the view. However the Ajax success call can assuredly call one of the controller's ActionResults to update the view and thereafter its related Partials in that view ,,,
the controller action in tha main part of the ajax call that DOES WORK needs to be marked EmptyResult & [HttpPost]
The controller action that really fires up an ActionResult to update your view ,, in my case, just returns the view and the newly modified model... and again note its called by the Success function of the previous cited ajax function The last code posting above pretty much covers it all

There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'print_ad_option_id'

So I have method in which I do some ajax:
function prodChange() {
console.log(this.value);
// ajax
var url = '#Url.Action("GetAdvProdList", "Contract")' + '?prod_id=' + this.value;
$.ajax({
url: url,
type: 'GET',
success: showAdvProd,
error: function() {
console.log("FAILSHAKUREHKGAHH");
}
});
}
The ajax returns successfully and calls this controller method.
public ActionResult GetAdvProdList(int prod_id) { // product id
// get advertising products for this product
OutlookMediaEntities1 db = new OutlookMediaEntities1();
var advsList = from printAdOption in db.print_ad_option
where printAdOption.print_product_id == prod_id
select printAdOption;
List<SelectListItem> adv_list = new List<SelectListItem>(); // list of ads
List<print_ad_option> advs = advsList.ToList(); // list from db
foreach (print_ad_option av in advs)
{
SelectListItem temp_item = new SelectListItem();
temp_item.Text = av.name;
temp_item.Value = av.print_ad_option_id.ToString();
adv_list.Add(temp_item);
}
ViewData["advproducts"] = new SelectList((IEnumerable<SelectListItem>)adv_list.ToList(), "Value", "Text");
return null;
}
I'm returning null because it doesn't work if I return View or PartialView, and I don't think I want it to return those things anyway. All I want is the viewdata stuff to be set.
The ajax worked well before I added code to use the view data. Unfortunately when I try to use the new ViewData in the ajax success method, I get this error:
"There is no ViewData item of type 'IEnumerable' that has the key 'print_ad_option_id'"
The thing is that I get this error when I first load the page, so it seems to be attempting to evaluate the "#Html.DropDownListFor..." before the showAdvProd function is called:
// called when the ajax returns a list of adv prods in a viewdata
function showAdvProd() {
// add drop down
$("#drdn1").append('#Html.DropDownListFor(m => m.print_ad_option_id, ViewData["advproducts"] as SelectList)');
}
The function that does ajax is called when an item is selected from a (different) dropdown menu, but with this error the page doesn't even load, so obviously the ajax function is never called and thus the controller method never called. So of course it won't recognize the viewdata...
I'm similarly creating a dropdown menu in another part of my form, using viewdata but without ajax, and it works fine. So I think something is wrong with my ajax or my controller method, not with how I'm using the viewdata.
Thank you in advance for any help!
The problem is that on your initial page load, the view engine will evaluate all the code blocks - anything with a '#' symbol in front of it. Thus it will try and look for a ViewData item called advproducts before it exists, even though that reference is within a javascript function that hasn't been called yet. Remember - code blocks (such as #Html.blahblahblah() are evaluated server side, while you are expecting your ajax to run on the client side, after the page has been sent to the client.
A couple of options: Returning a partial view should work. You could return a partialview that contains a dropdown and fill it from the ViewBag. That would look like this:
initial page:
...
<div id="advProductsSection"></div>
...
Your ajax would call the same function, but would return a partial view:
public ActionResult GetAdvProdList(int prod_id) { // product id
...
ViewData["advproducts"] = new SelectList((IEnumerable<SelectListItem>)adv_list.ToList(), "Value", "Text");
return View("_AdvProducts");
}
And then a partial view (Here named _AdvProducts.cshtml):
#Html.DropDownList("className", (IEnumerable<SelectListItem>) ViewBag["advproducts"])
Your ajax function would need to change to replace the div with the new partial:
success: function (result) {
$('#advProductsSection').html(result);
}
Or something like that..
A second alternative is to return JSON from the Action Method and populate a dropdown with that.
Your Controller:
...
return JSON(adv_list.ToList());
}
Then in your ajax success func:
success: function(list) {
// states is your JSON array
var $dropdown = $('#Dropdown');
$.each(list, function(i, product) {
$('<option>', {
value: list.Value
}).html(list.Text).appendTo($dropdown);
});
}
You'd need to cleat the dropdown again when prodchange is called.

ASP.Net MVC 3 Drop Down List

I am developing an ASP.Net MVC 3 Web Application. One of my Razor Views contains a few Textboxes and a Drop Down List. When the User selects an option from the Drop Down List, I need a Partial View, or something like this, to appear below the Drop Down List preferable without a post back.
The thing is, it isn't as easy as a simply JQuery Hide and Show for the Partial View, when the User selects an option from the Drop Down List, I need their option to be sent to a method in the Controller, perform some logic based on this option, and then return some data to the Partial View.
I haven't really got much experience with AJAX, but I get the feeling this is the technology I need to use in order to fulfil my problem.
Has anyone ever had to code anything similar to what I have described above? And if so, is AJAX what I need to use?
Also, if anyone knows of any tutorials or code snipets I could look at to help, that would be greatly appreciated.
Thanks.
UPDATE
I have followed Ryan's answer, but unfortunately I am still having some problems. I have created the following JavaScript file which is then referenced in my View
$(document).ready(function () {
$("#myDDL").change(ChangeEventOfDDL);
function ChangeEventOfDDL(){
var dropDownValue = $('#myDDL').val();
//alert(dropDownValue);
$.ajax({ type: "GET",
url: '#Url.Action("SomePartialView","testAjax")',
data: {
id: dropDownValue
},
success: function(data) {
$('#someDivToLoadContentTo').html(data);
}
});
}
});
View
<select id="myDDL">
<option></option>
<option value="1">F1</option>
<option value="2">F2</option>
<option value="3">ST1</option>
<option value="4">ST2</option>
</select>
<div id="someDivToLoadContentTo">
</div>
My Controller then looks like this
public class testAjaxController : Controller
{
//
// GET: /testAjax/
LocumEntities context = new LocumEntities();
public ActionResult SomePartialView(int id)
{
var test = "Hello World";
return View(test);
}
}
However, my method 'SomePartialView' never gets hit. Does anyone know why?
Thanks.
Yes Ajax would be the easiest thing to use here. There are plenty of good Ajax tutorials around, just remember that what Ajax does is effectively a background POST, so you can do everything you would normally do with MVC, except within an existing page.
The way I would get this to work would be to have your code something like this:
public class SomeController{
public ActionResult SomePartialView(){
// Do some logic
return View("SomePartial");
}
}
Your Ajax would be something like:
function ChangeEventOfDDL(){
$.ajax({
url: '#Url.Action("SomePartialView","Some")',
success: function(data) {
$('#someDivToLoadContentTo').html(data);
}
});
}
I hope that helps at least a little bit.
Crucially with Ajax, you can add a data object to the function, which is passed as a querystring. This means you can send values from your page quite easily with ajax. Working with the above example, the Javascript would be:
function ChangeEventOfDDL(){
var dropDownValue = $('#ddl').val();
$.ajax({
url: '#Url.Action("SomePartialView","Some")',
data: {
id: dropDownValue
}
success: function(data) {
$('#someDivToLoadContentTo').html(data);
}
});
}
The Id value is linked with the parameters of the method in your MVC class:
public class SomeController{
public ActionResult SomePartialView(int id){
// Do some logic
var model = MakeModelWithSupplierId(id);
return View("SomePartial",model);
}
}
And there you have an interactive partial view that has been populated with the value from your drop down.
Since a controller can also return a partial view, you can do the following:
$('#idofyourdropdown').change(function () {
var theValue = $(this).val();
$.post('#Url.Action("Action","Controller")', {nameOfParameter: theValue, function(data) {
$('#divWhereYouWantToAttachData').html(data);
});
});
On the change event of your dropdown, send the selected value to your desired controller action, which will pass it to the partial view and return the rendered html. The html is received in the data var and can be attached to the dom, wherever you want it (see jQuery documentation for this).
This is a common use case.
What you need to do is
create a controller method that can take the parameters you need (read about MVC model binding before you do so)
write javascript that will harvest the data you want from your form and make a call to your new controller method and render the results below
In jQuery it goes something like this:
$("#yourDIV").load('/area/controller/method', { property1: 'asasd', property2: 'asdasdadfa'})
The second parameter of this call should be prepared based on the data you harvest from your form. (if you don't know how, then learn javascript)

MVC: Best way for a hyperlink to post back to an ActionResult

I'm using a Html.BeginForm but I need a hyperlink to trigger a postback to a ActionResult (similar functionality to a LinkButton). I don't think that I can use an ActionLink because i'm not routing to a view with the same name as the ActionResult (or have I misunderstood :S).
Any help would be appreciated.
Thanks
I think you have two options (though the first isn't as flexible and can get messy)
1) style your submit button like a hyperlink (easy, but you'll probably end up using Html.BeginAjax or something like that)
2) Style a div, ActionLink, or some other element and serialize the form data on posting back using jQuery
If you can better describe the data being returned, we can better customize the dataType and success parameters below.
$(function () {
$('#myButton').click(function (e) {
e.preventDefault();
$.ajax({
url: '/MyController/MySuperAction',
type: 'POST',
data: $('#formId').serialize(),
dataType: 'json',
success: function (xhr_data) {
// in this particular example, you'll
// parse your JSON returned.
}
});
});
});
Edit
So, you're controller could look like
public ActionResult MySuperAction(FormCollection form) {
// I don't recommend using FormCollection
// You should stick to the view model pattern
// process your form
return Json(new { MyValue = "Textbox value" });
}
And you'd need to modify the success function above to something like
success: function(xhr_data) {
$('#MyTextBoxID').val(xhr_data.MyValue);
}

Resources