Cannot assign attributes to form using Html.BeginForm - asp.net-mvc

I have a form begun with the Html.BeginForm() helper method:
#using (Html.BeginForm(
null,null, new { #id = "MaintenanceForm", #class = "datatable", #nonvalidate="nonvalidate" }
))
and the form is rendered as:
<form action="(controller's name)/(current action's name)/MaintenanceForm?class=datatable" method="post">
The attributes such as id, class, and nonvalidate aren't assigned. Also I do not want a default Http Method. What can I do?

Your current code is matching with the below overload of BeginForm method
public static MvcForm BeginForm(
this HtmlHelper htmlHelper,
string actionName,
string controllerName,
object routeValues
)
The third parameter here is an object for the route values. These will be added as the querystring key value(s) to your form's action attribute value. That is the reason you are seeing those big url as the action attribute value.
If you want to specify the html attributes( Id,class etc), Use this overload which has a fourth parameter which takes the html attributes. The third parameter is the FormMethod.
public static MvcForm BeginForm(
this HtmlHelper htmlHelper,
string actionName,
string controllerName,
FormMethod method,
object htmlAttributes
)
This should work.
#using (Html.BeginForm("Create", "Post",FormMethod.Post,
new { #id = "MaintenanceForm", #class = "datatable", #nonvalidate = "nonvalidate" }))
{
}
Replace Create and Post with your action method name and controller name.

Related

ASP.NET MVC, CheckBoxFor() attribute problems

When I use CheckBoxFor() HtmlHelper like this:
#Html.CheckBoxFor(x => Model.IsDeleted, new { myCustomAttribute = "myCustomAttribute" })
my checkbox have attribute, but hidden element not have.
<input myCustomAttribute="myCustomAttribute" id="IsDeleted" name="IsDeleted" type="checkbox" value="true">
<input name="IsDeleted" type="hidden" value="false">
How add atribute to hidden element? I do not want to write custom HTML.
In my opinion the easiest way to achieve such functionality is to create custom helper :) Below simple helper from http://20fingers2brains.blogspot.com/2013/05/custom-checkbox-html-helper-in-mvc3.html :
public static class CustomCheckBoxHelper
{
//This helper accepts name attribute. This method in turns calls our second overload.
public static MvcHtmlString Custom_Checkbox(this HtmlHelper helper, string name)
{
return Custom_Checkbox(helper, name, false);
}
//This helper accepts name and isChecked boolean attribute.
public static MvcHtmlString Custom_Checkbox(this HtmlHelper helper, string name,bool isChecked)
{
return Custom_Checkbox(helper, name, isChecked, null);
}
//This overload accepts name, isChecked and htmlAttributes as parameter.
public static MvcHtmlString Custom_Checkbox(this HtmlHelper helper, string name,bool isChecked,object htmlAttributes)
{
//Creating input control using TagBuilder class.
TagBuilder checkbox = new TagBuilder("input");
//Setting its type attribute to checkbox to render checkbox control.
checkbox.Attributes.Add("type", "checkbox");
//Setting the name and id attribute.
checkbox.Attributes.Add("name", name);
checkbox.Attributes.Add("id", name);
//Adding the checked attibute based on parameter received.
if (isChecked)
checkbox.Attributes.Add("checked", "checked");
//Merging the other attributes passed in the attribute.
checkbox.MergeAttributes(new RouteValueDictionary(htmlAttributes));
return MvcHtmlString.Create(checkbox.ToString(TagRenderMode.Normal));
}
}

Passing parameter to controller action from a Html.ActionLink

Is there anything wrong with this html? I want to have a link in the masterpage to navigate to "CreateParts" view. I have action 'CreateParts' which have a parameter parentPartId in the controller 'PartList'.
<li id="taskAdminPartCreate" runat="server">
<%= Html.ActionLink("Create New Part", "CreateParts", "PartList", new { parentPartId = 0 })%></li>
My controller action is like
public ActionResult CreateParts(int parentPartId)
{
HSPartList objHSPart = new HSPartList();
objHSPart.Id = parentPartId;
return View(objHSPart);
}
When I click on 'Create New Part' in the menu in SiteMaster, I get exception. Please help me out of this.
You are using incorrect overload. You should use this overload
public static MvcHtmlString ActionLink(
this HtmlHelper htmlHelper,
string linkText,
string actionName,
string controllerName,
Object routeValues,
Object htmlAttributes
)
And the correct code would be
<%= Html.ActionLink("Create New Part", "CreateParts", "PartList", new { parentPartId = 0 }, null)%>
Note that extra parameter at the end.
For the other overloads, visit LinkExtensions.ActionLink Method. As you can see there is no string, string, string, object overload that you are trying to use.
You are using the incorrect overload of ActionLink. Try this
<%= Html.ActionLink("Create New Part", "CreateParts", "PartList", new { parentPartId = 0 }, null)%>
Addition to the accepted answer:
if you are going to use
#Html.ActionLink("LinkName", "ActionName", "ControllerName", new { #id = idValue, #secondParam= = 2 },null)
this will create actionlink where you can't create new custom attribute or style for the link.
However, the 4th parameter in ActionLink extension will solve that problem. Use the 4th parameter for customization in your way.
#Html.ActionLink("LinkName", "ActionName", "ControllerName", new { #id = idValue, #secondParam= = 2 }, new { #class = "btn btn-info", #target = "_blank" })

Providing ID in ActionLink() or RouteLink()?

I'm new to MVC and would like to add a link to something like ~/Destinations/35, where it would refer to the Index view of the Destinations controller, and 35 is the ID of the destination to be displayed.
Neither ActionLink() or RouteLink() appear to allow me to create a link such as this.
Also, I tried something like this:
<table>
#foreach (var d in ViewBag.Results)
{
<tr>
<td>
#Html.ActionLink(
String.Format("<b>{0}</b>", #Html.Encode(d.Title)),
"Details", "Destinations")
</td>
</tr>
}
</table>
But I get the following error on the ActionLink line, which I don't understand.
'System.Web.Mvc.HtmlHelper' has no applicable method named 'ActionLink' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
Can someone help me create this link?
The first problem with your code is that you are trying to use HTML in the link text (the <b> tags) which is not possible because by design it always HTML encodes.
So assuming you didn't want HTML in the link you could do this:
#Html.ActionLink(d.Title, "Details", "Destinations", new { id = "35" }, null)
And assuming you need HTML inside the anchor you have a couple of possibilities:
Write a custom ActionLink helper which won't HTML encode the text (recommended) and then use like this:
#Html.MyBoldedActionLink(d.Title, "Details", "Destinations", new { id = "35" }, null)
Something along the lines:
<a href="#Url.Action("Details", "Destinations", new { id = "35" })">
<b>#d.Title</b>
</a>
and since I recommend the first approach here's a sample implementation of the custom helper:
public static class HtmlExtensions
{
public static IHtmlString MyBoldedActionLink(
this HtmlHelper htmlHelper,
string linkText,
string actionName,
string controllerName,
object routeValues,
object htmlAttributes
)
{
var anchor = new TagBuilder("a");
anchor.InnerHtml = string.Format("<b>{0}</b>", htmlHelper.Encode(linkText));
var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
anchor.Attributes["href"] = urlHelper.Action(actionName, controllerName, routeValues);
anchor.MergeAttributes(new RouteValueDictionary(htmlAttributes));
return new HtmlString(anchor.ToString());
}
}

html.actionlink

i'm just starting to use asp.net mvc..
since i'm not familiar with it, i just want to ask a question about actionlink html helper..
i have this code in my index.aspx home view..
<% Dim _news As datatable = ViewData.Model%>
<% For count As Integer = 0 To _news.Rows.Count - 1%>
<% Dim id As Integer = _news.Rows(count).Item("IDnews")%>
<%=_news.Rows(count).Item("newsTitle")%>
<p>
<%=_news.Rows(count).Item("newsContent")%><br />
<%=Html.ActionLink("Read More..", "NewsPublic", "Administration", New With {id})%>
</p>
<%Next%>
if i click the actionlink, i was expecting it will render me to this url:
/Administration/NewsPublic/7
but rather it gives me this url :
/Home/NewsPublic?Length=14
does actionlink pass id in the same controller only?
thank you in advance!
To render link to /Administration/NewsPublic/7 you should use
<%=Html.ActionLink("Read More..", "NewsPublic", "Administration",
New With {.id = 7}, Nothing)%>
Fifth parameter makes compiler to choose
ActionLink(string linkText, string actionName, string controllerName,
object routeValues, object htmlAttributes)
extension method overload instead of
ActionLink(string linkText, string actionName, object routeValues,
object htmlAttributes)
And don't forget to add parameter assignment
New With {.id = 7}
instead of
New With {.id}
By default, Html.ActionLink will use the current controller. But there are about a dozen overloads of ActionLink(), and there are multiple versions of it that will accept a controller parameter. Try:
Html.ActionLink("Read More...",
"NewsPublic",
"Administration",
New With { .id = id },
null)

PartialView Dynamic BeginForm Parameters

If I have the below PartialView
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Models.Photo>" %>
<% using (Html.BeginForm("MyAction", "MyController", FormMethod.Post, new { enctype = "multipart/form-data" })) { %>
<%= Html.EditorFor( c => c.Caption ) %>
<div class="editField">
<label for="file" class="label">Select photo:</label>
<input type="file" id="file" name="file" class="field" style="width:300px;"/>
</div>
<input type="submit" value="Add photo"/>
<%} %>
As you can see, the Action and the Controller are hard coded. Is there a way I can make them dynamic?
My goal is to have this partial view generic enough that I can use it in many places and have it submit to the Action and Controller it is sitting within.
I know I can use ViewData but really don't want to and likewise with passing a VormViewModel to the view and using the model properties.
Is there a nicer way than the two I listed above?
I Checked the source code of MVC and dig into the System.Web.Mvc --> Mvc --> Html --> FormExtensions so I find you can write some code like :
public static class FormHelpers
{
public static MvcForm BeginFormImage(this HtmlHelper htmlHelper, IDictionary<string, object> htmlAttributes)
{
string formAction = htmlHelper.ViewContext.HttpContext.Request.RawUrl;
return FormHelper(htmlHelper, formAction, FormMethod.Post, htmlAttributes);
}
public static MvcForm FormHelper(this HtmlHelper htmlHelper, string formAction, FormMethod method, IDictionary<string, object> htmlAttributes)
{
TagBuilder tagBuilder = new TagBuilder("form");
tagBuilder.MergeAttributes(htmlAttributes);
// action is implicitly generated, so htmlAttributes take precedence.
tagBuilder.MergeAttribute("action", formAction);
tagBuilder.MergeAttribute("enctype", "multipart/form-data");
// method is an explicit parameter, so it takes precedence over the htmlAttributes.
tagBuilder.MergeAttribute("method", HtmlHelper.GetFormMethodString(method), true);
htmlHelper.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.StartTag));
MvcForm theForm = new MvcForm(htmlHelper.ViewContext);
if (htmlHelper.ViewContext.ClientValidationEnabled)
{
htmlHelper.ViewContext.FormContext.FormId = tagBuilder.Attributes["id"];
}
return theForm;
}
}
I'm not sure this is exactly what you really want to get but I'm sure you can get it if you change this lines in way satisfies your needs.
Hope this helps.

Resources