InvalidOperationException error in cshtml - c#

MVC Application in C#.
A Partial View Displays a dropdown and an "Okay" button. The dropdown displays a list of allowable "Routers" (persons who can route documents in the application). The user can select a person from the dropdown and then have them made the "Router" by clicking the "Okay" button. The code correctly changes the persons designated as router, but the error InvalidOperationException is generated every time the "OKay" button is clicked. The error description is "There is no ViewData item of type 'IEnumerable' that has the key 'RouterElect'."
Part of screenshot:
The code:
#model JudicialPortal.ViewModels.PortalIndexView
<div class="tile">
Change Current Router
#Html.DropDownListFor(x => x.RouterElect, Model.JPortalChamberUsersAsItems, new { #id = "changeCurrentRouterInput", #class = "m-wrap", #onchange = "" })
<button type="button" class="m-btn green-stripe" onclick="changeCurrentRouter();"
style="color: #444; text-decoration: none;">
Okay</button>
</div>
Router Elect is defined in the ViewModel referenced at the top of the code (PortalIndexView):
public string RouterElect { get; set; }
The partial view is called from another cshtml page:
<div id="ChangeRouterSection" class="live-tile" data-mode="carousel" data-direction="vertical" data-delay="7000">
#{Html.RenderPartial("_ChangeCurrentRouter");}
</div>

Related

How to check which button clicked and also pass id from view to controller

I have a list in my view and each row in my list contains view or submit buttons based on the status. It the application is complete then View button else Edit&Submit button. When a user clicks any button I need to check which button clicked and redirect the action to the respective controller. The challenge here is how do I pass which button clicked and also the id from view to controller?
View :
This only passes which button clicked to the controller. But also I need to pass id. without passing id I cannot display any data in my Edit&Submit page and View pages.
#if (#list.Completed == true)
{
<div class="col-md-2">
<button class="btn" type="submit" name="View" id="View" value=View>View</button>
</div>
}
else
{
<div class="col-md-2 ">
<button class="btn" type="submit" name="EditSubmit" id="EditSubmit" value=EditSubmit>Edit&Submit</button>
</div>
}
Controller:
[HttpPost]
public ActionResult CompleteList(string View, string EditSubmit, int mylistid)
{
if (View == "View")
{
return RedirectToAction("Viewcontoller", "Primary");
}
if (EditSubmit == "EditSubmit")
{
return RedirectToAction("EditAndSubmit", "Secondary");
}
return View();
}
Is there any way I can pass id as well as button clicked to controller and perform the actions inside one ActionResult ?
In your controller, the value of the EditSubmit property in the CompleteList method is the value property of the button. This is mapped based on the name of the button. So, if you set the value equal to an ID, that is was will be received in the controller. For example, in the button definition below, the controller method would receive the value of "12345" in the EditSubmit parameter.
<button class="btn" type="submit" name="EditSubmit" id="EditSubmit" value="12345">Edit&Submit</button>

Passing selected button value from view to controller

I would like to pass the selected button value to the controller. See my code below.
In my controller I am passing through the ProductId which I will then use to set up my product value inside my controller.
Controller:
public ActionResult PlaceOrder(int ProductId, string OrderType)
{
// Do something
}
Inside my view I have a foreach loop which will create radio like buttons and I have also got a hiddenfor(SelectedProductId)
View:
<div class="panel panel-primary">
<div class="panel-heading">Panel Name</div>
<div class="panel-body">
<div class="row">
<div class="form-group">
#Html.HiddenFor(m => m.SelectedProductId)
#if (Model.Products != null && Model.Products.Count > 0)
{
<div class="btn-group" data-toggle="buttons">
#foreach (var product in Model.Products)
{
<label class="btn btn-default productButton">
<div class="labelProduct">#Product.Name</div>
<input type="radio" name="ProductGMX" id="#("product" + #product.Id)" autocomplete="off" checked data-id="#product.Id">
</label>
}
</div>
I will want to pass the Product Id in the ActionLink which will then pass it to the controller but I am not sure how this can be achieved
Button Click:
#Html.ActionLink("Order with standard delivery", "PlaceOrder", "Standard", new { ProductId = ?, OrderType = "Standard delivery" }, new { area = "Standard" })
#Html.ActionLink("Order with Next day Delivery", "PlaceOrder", "Elevated", new { ProductId = ?, OrderType = "NextDay" }, new { area = "Elevated", })
You either need to use JavaScript to update the ActionLink's url whenever the product changes, using the data-id from the radio button.
Or
Use submit buttons instead of ActionLinks, and set the value on the radio button to the product id. You'll need to put some logic in your controller to handle the two different buttons.
Those aren't buttons. They're links, which don't participate in the form submission.
Use real buttons, i.e. <button></button> and give them a name. Then you can see which was clicked by inspecting the Request object:
<button name="_StandardDelivery">Order with standard delivery</button>
Then in your action:
if (Request["_StandardDelivery"] != null) {
// user chose standard delivery
}

ListBoxFor not unselecting between posts

I have following code in View:
<div class="row form-group">
#Html.LabelFor(x => x.GroupCriteria.Name, Translation.Name, new { #class = "col-sm-4 control-label" })
<div class="col-sm-4">
#Html.ListBoxFor(m => m.GroupCriteria.Name, Model.NameList, new { #class = "multi-select-custom" })
</div>
</div>
...
<button type="submit" name="removeCriterion" value="Name">X</button>Name: #(string.Join(",", Model.GroupCriteria.Name))</button>
...
<button type="submit">#Translation.Update</button>
And in controller:
public ActionResult GetUsers(GroupCriteriaModel groupCriteria, string removeCriterion)
{
if("Name".Equals(removeCriterion)) groupCriteria.Name.Clear();
...
return View(modelWithCriterias);
}
Now what is happening:
When I select/unselect some values by clicking in select then click "Update", everything works fine: selection in returned page is same as what was posted.
Now i click "X" to clear "Name". "removeCriterion" is equal to "Name", so Name list is cleared (in debugger I see it is empty). Debugger in View: "Model.GroupCriteria.Name" is still empty, none of "Model.NameList" is "Selected" (set true). But returned HTML contains same selection as before (same items have attribute 'selected="selected"').
Is this some kind of caching done by MVC? How to avoid this?
Most likely it is being binded from ModelState, so you should clear it:
if("Name".Equals(removeCriterion))
{
groupCriteria.Name.Clear();
ModelState.Clear();
}
If you want to perform the operation in more specific way, you can use ModelState.Remove() in order to remove only the state related to your ListBox.

MVC4 Razor - bind object Id from foreach loop to Url.Action that's outside the loop

I'm not sure if this can be done as the Url.Action() is trying to access a variable that's only in the foreach's scope - maybe using jQuery?
I have a strongly typed partial view that takes a view model that contains a list of search results.
I iterate through the list and each result is displayed in summarised form. Beside each item in the list there's a button that (should) when clicked launches a modal window that displays more detailed information about the list item. So if there's 10 items in the list there's going to be 10 correspdonding 'More info' buttons.
Partial View:
<div>
#foreach (var result in Model.SearchResults)
{
<div class="basic-search-result">
<div class="row-fluid">
<img class="span3" src="http://some-img.jpg" />
<div class="span3">
<div class="address">
#result.Address.TownCity<br />#result.Address.County
</div>
<div>
€#result.MonthlyRate Monthly
</div>
</div>
<div class="span3 offset1" id="basic-search-result-btns">
<button class="btn btn-primary btn-block" id="btn-show-modal-from-get-all">More info</button>
</div>
</div>
</div>
}
</div>
Just below the foreach loop I define the modal (ViewProperty is a controller action that returns a partial that contains the modal's body):
<div class="modal hide fade in" id="modal-view-property-from-get-all"
data-url="#Url.Action("ViewProperty", "ResidentialProperties", new { id = result.ResidentialPropertyId })">
<div id="view-property-from-get-all-container"></div>
</div>
When one of the buttons is clicked, it should launch a modal. Handled like this:
<script type="text/javascript">
$(document).ready(function () {
$('#btn-show-modal-from-get-all').click(function () {
var url = $('#modal-view-property-from-get-all').data('url');
$.get(url, function (data) {
$('#view-property-from-get-all-container').html(data);
$('#modal-view-property-from-get-all').modal('show');
});
});
});
I know that the Id I'm binding in the Url.Action() is outside of the scope of the foreach. Is it possible to somehow get the result.ResidentialPropertyId and pass it to the Url.Action() dynamically when a button is clicked?
To prove it's working, I placed the Url.Action() in the foreach loop, but this only launched a modal for the first item in the list. Can what I'm trying to do be achieved?
Do not include the Id in the data-url
<div class="modal hide fade in" id="modal-view-property-from-get-all"
data-url="#Url.Action("ViewProperty", "ResidentialProperties")">
<div id="view-property-from-get-all-container"></div>
</div>
With that code the data-url will have a value ResidentialProperties/ViewProperty.
Then include the Id on each row to your button or you can read it from it's container element. I also suggest you remove the id of the button and maybe just have a class to ensure that the ajax call won't get executed for all instances of your buttons
// assuming Id is the identifier per row
<button class="btn btn-primary btn-block show-modal"
data-id="#result.Id">More info</button>
and in your js do the following
$(document).ready(function () {
$('.show-modal').click(function () {
var url = $("#modal-view-property-from-get-all").attr('data-url');
var id = $(this).attr('data-id');
$.get(url + '/' + id, function (data) {
$('#view-property-from-get-all-container').html(data);
$('#modal-view-property-from-get-all').modal('show');
});
});
});

MVC 4 Clicking a Button to get a Partial Page

I am creating a page with a search property. The user will enter a number in the search field and hit the submit button. I need to be able to call a controller method in order to run the search code.
For now I am just trying to hit a partial page to just get some functionality in there. Below is the code I have so far. As of now nothing happens when I click the button. I hear Ajax was something to use so I have been playing with that a little. I am still learning the framework so bear with me.
<div class="span6 roundedCorners">
<div class="row-fluid Title">
<div class="span6">
Search Area
</div>
</div>
<div class="row-fluid individual">
<div class="row-fluid">
<div class="span4"><span class="pull-right fieldDescription">Number</span></div>
<div class="span8"><input /></div>
</div>
<div class="row">
<div class="span12" id="adminSubmitButton">
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "_adminDetails" }))
{
<button type="submit" class="btn btn-inverse">Submit</button>
}
</div>
</div>
</div>
Your form is empty, it only has a submit button. You will need to move your search button inside the form. Something like this:
Model
public class SearchModel
{
[Required]
public string Query { get; set; }
}
View
#model SearchModel
...
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "_adminDetails" }))
{
#Html.EditorFor(m => m.Query)
#Html.ValidationMessageFor(m => m.Query)
<button type="submit" class="btn btn-inverse">Submit</button>
}
<div id="_adminDetails"></di>
Note: Make sure you have an element with id _adminDetails
Your controller will have to take the model and perform the search. Example:
Controller
[HttpPost]
public ActionResult Index(SearchModel model)
{
//do something with your model (perform search)
return View(results);
}
Alright, I have it partially working now. When i click the button I am able to call the controller method using:
function adminButton()
{
$("#adminDetails").load("#Url.Action("ControllerMethod", "ControllerName")");
}
The #Url.Action helper allows me to call the method which returns a partial view. This is a step in the right direction. But from what I am reading I should be able to use the following Url helper instead of the #Url.Action:
"#Url("ControllerMethod", "ControllerName")/" + submitButton.Value
I have tried some variations and I am still doing some reading to figure out a solution. Is there a helper that would let me do this?
Thanks for the help guys. I did end up getting my problem solved friday evening. Basically what I did was load the partial page when the button was clicked through the help of JS/jQuery and the Razor #Url.Action() to call the controller method that returns a PartialView:
<script type="text/javascript">
function adminButton()
{
var link = "#Url.Action("ControllerMethod", "ControllerClass", new {
number = -1})";
var num = parseInt($("#number").val());
link = link.replace(-1, num);
$("#details").load(link);
}
</script>

Categories

Resources