Asp MVC ajax dynamic parameters - ajax

I'm not sure how to phrase this one but here goes nothing.
I have a controller that has two parameters: FindingId, TagId
public JsonResult Add(int FindingId, int TagId)
I have an Ajax ActionLink to call it:
<%: Ajax.ActionLink( "Add", "Add", "FindingTag",
new { FindingId = Model.FindingId },
new AjaxOptions {
HttpMethod = "Post"
})
%>
I then have a dropdownlist of available Tags:
<%: Html.DropDownListFor(m => m, Model.AvailableTags, "Select Option..", new { id = "finding_" + Model.FindingId + "_AvailableTags" } )%>
The parameters are populated in the following way:
You can see above that I am filling in the FindingId when the model is being rendered since that will always be the same in this subsection. This view is being rendered multiple times for different Findings so that FindingId will change per model.
The TagId however should come from the selected value of the DropDownList.
I am not mapping this particular request to a viewmodel to pass in so the dropdownlist is not being bound to a particular property. I have also created a route for
/FindingTag/Add/{FindingId}/{TagId}
So here are the questions this has opened and I'm really hoping someone can help me out as this stuff is really knew to me.
1) I found that the href is being rendered as Add?FindingId=## and I was curious if I can force that to render to Add/##
2) Is there an easier way I can get the value from the dropdownlist to append to the href to create the route mentioned above?
Most of the time in the project I have been using jQuery for my ajax calls so I would just manually build a URL from scratch, but I was really hoping to use the MS versions for practice. Does this seem irrational? Let me know if you have any suggestions or insight..
Edit:
I am not sure if this is the way to go about this. I am finding people saying to use a form and submit that, but if I have this as a subsection of an already strongly-typed partial view, how do I get the values to be sent back in a form I can use that isn't the fullfledged model? I would prefer to keep it to the 2 parameters and not a complex object if possible.

Related

Proper way for delete function in ASP.NET MVC 4 WebGrid

I just started using WebGrid and I have been searching a proper way to delete a row.
But I don't want to use solutions which redirects the user an other window. I just want that when the user clicks delete then pop up a confirm window and if the user choose yes, delete the data and refresh the page, but with ajax.
I have found a way to do this, but I have not seen other people do it on the Internet in the same way and I want to know if it is a good practice to follow it in the future.
In the WebGrid I have the following column definition:
grid.Column(header: "", format: #<text> <button type="submit" name="Delete" value="#item.Id">Delete</button></text>)
It is in a #Ajax.Beginform(...) { ... }
In my Controller I check if a Delete button was clicked and get the Id this way:
[HttpPost]
public ActionResult Index(ManageOvertimesViewModel model, FormCollection formCollection)
{
...
if (formCollection["Delete"] != null)
{
int id = int.Parse(formCollection["Delete"]);
//Delete the data
return PartialView("IndexPartial", model);
}
...
}
When I delete something in this view other data displayed can be changed, so I need to have the posted ViewModel to recreate some DropDowns in the view and this is the reason I don't use Ajax.ActionLink to solve the delete.
So is it a good way to achieve delete?
Here you have example from View:
grid.Column("", "", canSort: false, format:#<b>#Html.ActionLink("Delete", "DeletePrizeRun", new { id = item.ID })</b>, style: "column")
Here code from controller:
public ActionResult DeletePrizeRun(int id)
{
using (var context = new ExampleDataContext())
{
var prizeRun = context.PrizeRuns.FirstOrDefault(p => p.id == id);
context.PrizeRuns.Remove(prizeRun);
context.SaveChanges();
}
}
For your solution the Grid has to be inside the the Ajax form. The ajax form will do partial updates and the grid will do (if you specify an ajax target which you must if you want to avoid page reloads, at least if you are using paging and sorting with pager / sort headers generated by WebGrid). That is where my headache with a similar solution started. The Grid started to behave strangely when sorting or paging, e.g. the controller was executed multiple times.
I ended up giving up on WebGrid and I am now using html tables with razor commands which works great and provides much better control.
I recommend not to use WebGrid for anything but the most simple demo.
Other than that I see no problem with your approach, using name / value to pass data to the controller worked for me.

EditorFor parameters in Action MVC3

Having a bit of trouble figuring something out.
I've got an Action:
public ActionResult FareTypeSelector(SearchTypes searchType, SearchSource searchSource)
{
IFareTypeOptionsRepository fareTypeOptionRespoitory = new FareTypeOptionsRepository();
FareTypeOptions fareTypeOptions = fareTypeOptionRespoitory.GetFareTypeOptions(searchSource, searchType, _authentication.UserLoggedIn.CallCentreUser, _authentication.UserLoggedIn.AgencyProfile.BranchCode);
return View();
}
I've created an 'Editor', i.e. a file in EditorTemplates called FareTypeSelector.cshtml.
I want to bind my editor to a property of the model of the page that contains the editor. But I also want to pass some parameters into my action, i.e. (SearchTypes searchType, SearchSource searchSource). The idea being that the data displayed in the editor is based on this information passed in. Now I can't quite figure out if:
Is this possible?
whats the markup needed in the main view to render
this, pass the parameters and bind the resulting selected value into the main model?
Ta in advance
EditorTemplates are used for Data items from your model, not Action methods. They're using only in your view to render a specific model (or member of a model)

ASP.Net MVC 3 - DropDownListFor fails to select the value form the model if HtmlFieldPrefix is set on the partial view

when using
<%= Html.DropDownListFor(model => model.FeeTypeId, Model.GetFeeTypes(), new { })%>
in this case the right option is selected according to Model.FeeTypeId when the select is rendered.
BUT
if you render the form using a partial view, passing it a specific HtmlFieldPrefix (you will need it if,for example, you want to render two identical views and want different ids the elements)
<% Html.RenderPartial("path-to-partial-view", Model, new ViewDataDictionary() { TemplateInfo = new TemplateInfo() { HtmlFieldPrefix = "myPrefix" } }); %>
then the value will not be selected.
looks similar to the problem at DropDownListFor in EditorTemplate not selecting value but from different cause.
looked in the MVC 3 source and seems like the problem is at the SelectInternal method
it uses the htmlHelper.ViewData.Eval(fullName);
which fails to get the value by the full name when it contains the prefix,
TextBoxFor doesn't fail as it passes the value of the expression to InputHelper so it doesn't get to use the ViewData.Eval
just to be sure tested it at the partial view:
in the partial view the following will print "myPrefix.FeeTypeId"
<%= Html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName("FeeTypeId") %>
and the following will print "by property name: [value] by full name: [empty string]"
<%="by property name: " + Html.ViewData.Eval("FeeTypeId")%><br />
<%= "by full name: " + Html.ViewData.Eval(Html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName("FeeTypeId"))%>
The only solution i found is to generate a List at Model.GetFeeTypes() and mark the option i want as selected:
<%= Html.DropDownListFor(model => model.FeeTypeId, Model.GetFeeTypes(Model.FeeTypeId), new { })%>
don't really like this solution + i know i can create the List in the partial view which is also ugly,
is there another solution to this?
I have discovered that this is a bug in MVC. It's not fixed, though there is a work around.
See my question answered by myself (I had the same problem before finding your post).
MVC4 binding drop down list in a list (bug)
Regards
Craig

how to retrieve value of dropdown selection when form is not been submitted yet

I have following code
#using (Html.BeginForm())
{
#Html.DropDownListFor(m => m.IDs, new SelectList(Model. IDs), Model.SelectedID)
}
So user selection from this combo bind to SelectedID property of the model. My understanding is that this binding happen only when form is submitted. Let’s say from the same page, I need to do an AJAX call but at this point ) Model.SelectedID does not provide any value because form hasn’t been submitted yet (although user has selected something from drop down). Any ideas how to best deal with this situation?
You can use javascript.
var selectedValue = $("#IDs").val();
bind a change event to your DD
$("#DDL_ID").change(function(){
var currVal = $(this).val();
//do ajax
});
As others have pointed you would get this value with javascript on the change of the drop down list.
I wanted to point out however, that your understanding of the overload you are using for the drop down list is incorrect. This overload will display a default option box label.
For example you could prompt the users to select select something from the list:
#Html.DropDownListFor(m => m.IDs, new SelectList(Model. IDs), "Select Something...")
If you were to post the form in your example as is, you can see the selected item come across in the form. If your view model is setup in such a fashion the model binder would take over and bind this value to your "SelectedID" property.
[HttpPost]
public string DropDown(FormCollection form)
{
var selectedItem = form["IDs"];
return selectedItem;
}

mvc 3 html attributes

i have been playing around with MVC. I am currently stumped on with html helper methods. One thing i have noticed is that I cant really cant apply the ASP.NET Web Form logic into MVC. To explain further, in ASP.NET I could create a Label control and assign it some text data and then read the text data.
However, in MVC, I cant seem to do the same with #Html.LabelFor/#Html.Label, I have realised that once you do a POST from your form, the value from the Label is not bound back into my view model. However, if I use an EditorFor or TextBoxFor, I can get values bound to my viewmodel upon POST.
My question what html hlper method should I use to display text as readonly but yet be able to bind back to my viewmodel upon post ? I have tried TextBoxFor with its html attributes set to disabled and readonly but no luck.
Appreciate any pointers.
thanks
You should be able to bind the readonly attribute to the TextBox by passing in htmlAttributes as the 2nd parameter of the TextBoxFor method:
<%=Html.TextBoxFor(m => m.SomeProperty, new { #readonly = "readonly" }) %>
On MSDN: InputExtensions.TextBoxFor Method (HtmlHelper, Expression>, Object)
If you're trying to maintain the Label value you can use a combination of the LabelFor and HiddenFor methods.
I don't know why you would need to do this though, since you should be able to get the DisplayText attribute or the Property Name from the property.
<%=Html.LabelFor(m => m.SomeProperty) %>
<%=Html.HiddenFor(m => m.SomeProperty) %>
but this doesn't make a lot of sense since the usual syntax would be:
<%=Html.LabelFor(m => m.SomeProperty) %>
<%=Html.TextBoxFor(m => m.SomeProperty) %>
Note that if you use the disabled attribute the input will not be posted when the form is submitted
This is expected behaviour, only values form elements are added to your Model on POST so your label will be ignored. To get around this duplicate your label value in a hidden field
Html.HiddenFor(model => model.FieldName)
or
Html.Hidden("FieldName", model.FieldName)

Resources