Adding bootstrap classes with html helper methods not working? - c#

Is there any way to add bootstrap classes like form-control to asp.net mvc html helper methods like #html.Textbox("searchString");?
this is the code I have in the view
#this is the html output for the search bar taking searchstring param from controller in htmlhelper#
#using (Html.BeginForm())
{<div class="jumbotron">
<div class="row">
<div class="col-md-12">
<p>
Search: #Html.TextBox("SearchString")
<input class="btn btn-info" type="submit" value="Search" />
</p>
</div>
</div>
</div>
}
It seems like everything is playing nice with bootstrap except the #Html.Textbox and its messing up my UI.
is there a way to affect the #Html.Textbox with bootstrap form-control class?
ps the "SearchString" variable comes from my controller.

Yes.
You have the possibility to add HtmlAttributes:
#Html.TextBox("SearchString", null, new { #class = "form-control" })
And if you're using a property from your #model:
#Html.TextBoxFor(m => m.Property, new { #class = "form-control" })

#Html.TextBox("SearchString", null, new {#class="form-control"});

One variation of the #Html.TextBox helper takes an anonymous object that you can use to pass in HTML attributes. You would use it like:
#Html.TextBox("SearchString", null, new { #class = "form-control" })

Related

Alternate Way To Write Razor Code/ Can HTML Work Instead?

Is there anyway to rewrite razor code in html format to get the same results?
I honestly did not try anything but google a few solution but could not get help
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h3> Create new Genre</h3>
<hr />
<div class="form-group">
#Html.LabelFor(m => m.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(m => m.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(m => m.Name, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div>
<input type="submit" value="Create" class="btn btn-sm btn-success" />
#Html.Partial("_BackToListPartial")
</div>
IS there a pure html version of this code that will produce the same result without using lambda expression?
No errors, just asking for alternate ways
If you are using ASP.NET Core then you can use Tag Helpers, which look like standard HTML.
For example, #using (Html.BeginForm()) could instead use the form tag helper:
<form asp-controller="MyController" asp-action="MyAction" method="post">
</form>

c# mvc form: how to build view for simple feedback form leveraging the benefit of using html.editorfor?

I have simple input form (basically for feedback) with following fields:
Name, Gender, Mobile-Number, Complaint text. (To simplify I am not mentioning any POST action OR submit button on the form)
Currently, I have created following MVC structure:
public class ComplaintController
{
[HttpGet]
public ActionResult Index()
{
return View(); //This view displays the complaint form with all above fields
}
}
I read this and several other links where they suggest to use #Html.EditorFor as it creates UI based on model data-type.
Currently, I am not passing any model to the [HttpGet] view. If I want to use #Html.EditorFor, I need to pass my model to [HttpGet] Index View, how can I do that? What is best pratise to create such MVC forms?
Your Controller:
public ActionResult Index()
{
whateverModel d = new whateverModel();
return View(d);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(whateverModel m)
{
if (ModelState.IsValid)
{
//its valid, update your database or do soemthing useful here
return RedirectToAction("Success");
}
//its not valid reload the page and let data annotations show the error
return View(m);
}
Once you have your code in the controller then you can have visual studio auto-create your view. In your controller, right click the "d" in return View(d); and select "Add View." Change the Template to "create" and Model class to your Model (whateverModel in this example). It will auto generate the chtml page for you with the model imported and the editors already generated for you. Example auto generated view below. The you can work on styling and such.
cshtml:
#model YourSolution.Models.whateverModel
#{
ViewBag.Title = "Whatever";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Whatever</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Whatever</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.FriendlyName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FriendlyName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FriendlyName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Order, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Order, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Order, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Currently, I am not passing any model to the [HttpGet] view. If I want
to use #Html.EditorFor, I need to pass my model to [HttpGet] Index
View, how can I do that?
Hi sahil ,As a first step , create one model class like below
public class FeedBack
{
public string Name{get;set;}
public string Gender{get;set;}
public int Mobile-Number{get;set;}
public string Complaint{get;set;}
// other additional fields
}
And in the controller get method ,pass a model like below
public class ComplaintController
{
[HttpGet]
public ActionResult Index()
{
FeedBack OBJFeedback = new FeedBack();
return View(OBJFeedback);
}
}
And in a view , strongly type this model and post the data as you want to the controller post methods.
Here is the example of strongly typed view : http://www.c-sharpcorner.com/UploadFile/abhikumarvatsa/strongly-typed-views-in-mvc/
Important Note : In the get action method , since you dont want to display any values by default in the view , even if you dont pass model object it will work in the same way.
Hope the above information was useful
Thanks
Karthik
If you want to use #Html.EditorFor, then you mast pass the model to the view.What does #Html.EditorFor do? It makes the html tag like
<input class="text-box single-line" id="Name" name="Name" type="text" value="">
So if you do not want to pass the model to the view then you need to write the raw html tag like above. It is important to keep the html tag's name property same as the mvc's model property because when you want to post the data to the controller the name property of the html tag will map the mvc model property and get the corresponding value at the Controller method.
At the view(somthing.cshtml) you can use html tags, because .cshtml==.cs+html . So the whole code look like
Controller methods
public ActionResult FeedBack()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult FeedBack(FeedBackModel Model)
{
var feedBack = Model;
return View();
}
And the View
<form action="/Home/FeedBack" method="post" id="feedBackForm">
#Html.AntiForgeryToken()
<hr>
<div class="form-group">
<div class="col-md-5">
<label for="Name">Name</label>
</div>
<div class="col-md-5">
<input class="text-box single-line" name="Name" type="text">
</div>
</div>
<div class="form-group">
<div class="col-md-5">
<label for="Name">Gender</label>
</div>
<div class="col-md-5">
<select name="Gender">
<option value="male">Male</option>
<option value="female">Female</option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-md-5">
<label for="Name">MobileNumber</label>
</div>
<div class="col-md-5">
<input class="text-box single-line" name="MobileNumber" type="text">
</div>
</div>
<div class="form-group">
<div class="col-md-5">
<label for="Name">Complaint</label>
</div>
<div class="col-md-5">
<textarea class="text-box single-line" name="Complaint"></textarea>
</div>
</div>
<div class="col-md-5">
<input type="submit" value="Create" class="btn btn-default">
</div>
</form>
If you do not want to use submit then you can use ajax.

ViewBag property set but not accessible [duplicate]

This question already has answers here:
Can the ViewBag name be the same as the Model property name in a DropDownList?
(2 answers)
Closed 5 years ago.
I'm just trying to put a SelectList into the ViewBag but I can't access it right after.
Here's my code:
// GET: Content/CreateSerie
public ActionResult CreateSerie()
{
ViewBag.originalLang = new SelectList(db.Lang, "originalLang", "originalLang");
return View();
}
If I use the debugger to step right after the ViewBag.originalLang assignation and use the expression evaluator, I get
However, if I go deeper into the ViewBag I can see
This is really weird and I don't get why I can't access it normally. Of course, I can't access it from the view either.
EDIT: Here's my View as erdi yılmaz requested:
#model e08projh17.Models.Content
#{
ViewBag.Title = "Créer une série";
#Styles.Render("~/Content/css")
#Styles.Render("~/Content/themes/base/css")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/jqueryui")
}
<h2>CreateSerie</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Content</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<!-- Lots of stuff ... -->
<div class="form-group">
#Html.LabelFor(model => model.originalLang, "Langue originale", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.originalLang, (SelectList)ViewBag.originalLang, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.originalLang, "", new { #class = "text-danger" })
</div>
</div>
<!-- Lots of stuff ... -->
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>#Html.ActionLink("Back to List", "Index")</div>
#section Scripts { #Scripts.Render("~/bundles/jqueryval") }
Try this:
#Html.DropDownList("originalLang", null, htmlAttributes: new { #class = "form-control" } })
In your controller, you aren't returning a model to the view.. return View(/* empty here */);
So I don't know why you are using DropDownListFor. Instead use DropDownList
This is because the ViewBag is a dynamic type which means that it is resolved at runtime.
If you step through the debugger, you are looking at precompiled code and the ViewBag object has not yet been resolved by the DLR so you are unable to resolve the property.
What you are seeing inside the ViewBag when you "go deeper" are implementation details of how the data is collected for resolution.
Try this for dropdown
#Html.DropDownListFor(model => model.originalLang, (IEnumerable<SelectListItem>)ViewBag.originalLang, new { htmlAttributes = new { #class = "form-control" } })

TagBuilder not generating unqiue id attribute values across ajax requests

I have an issue where I'm using the same template to render some content on a page and the same template is used to render additional content on the page using an AJAX request.
The following code renders the partial razor view:
#model SearchBoxViewModel
<div class="smart-search">
#using (Html.BeginForm("Index", "Search", FormMethod.Get, new { #class = "form-horizontal", role = "form" }))
{
<div class="form-group">
<div class="hidden-xs col-sm-1 col-md-1 col-lg-1 text-right">
#Html.LabelFor(m => m.SearchPhrase, new { #class = "control-label heading" })
</div>
<div class="col-xs-8 col-md-9 col-lg-10">
#Html.TextBoxFor(m => m.SearchPhrase, new {#class = "form-control", placeholder = "for products, companies, or therapy areas"})
</div>
<div class="col-xs-4 col-sm-3 col-md-2 col-lg-1">
<input type="submit" value="Search" class="btn btn-default"/>
</div>
<div class="what-to-search hidden-11 col-sm-11 col-sm-offset-1">
<div class="checkbox">
<label>
#Html.CheckBoxFor(m => m.WhatToSearch, null, false)
#Html.DisplayNameFor(m => m.WhatToSearch)
</label>
</div>
</div>
</div>
}
</div> <!-- /.smart-search -->
The following code makes the AJAX request:
$.ajax(anchor.attr("data-overlay-url-action"))
.done(function (data) {
$("div.overlay").addClass("old-overlay");
$("div.navbar").after(data);
$("div.overlay:not(.old-overlay)")
.attr("data-overlay-url-action", anchor.attr("data-overlay-url-action"))
.hide()
.fadeIn();
$("div.old-overlay")
.fadeOut()
.removeClass("old-overlay");
anchor.addClass("overlay-exists");
});
So what you get is the same partial razor view output on the page twice, once during the page request and once during the AJAX request.
The problem is that TextBoxFor, CheckBoxFor, etc. all make use of TagBuilder.GenerateId to generate the id attribute value but it doesn't account for generating id's across multiple requests where AJAX might be involved. This results in the same id value being output on the page, causing JavaScript to break.
The following is the HTML that is output twice (once during the request and then added in a separate part of the page during an AJAX request):
<div class="smart-search">
<form role="form" method="get" class="form-horizontal" action="/PharmaDotnet/ux/WebReport/Search"> <div class="form-group">
<div class="hidden-xs col-sm-1 col-md-1 col-lg-1 text-right">
<label for="SearchPhrase" class="control-label heading">Search</label>
</div>
<div class="col-xs-8 col-md-9 col-lg-10">
<input type="text" value="" placeholder="for products, companies, or therapy areas" name="SearchPhrase" id="SearchPhrase" class="form-control">
</div>
<div class="col-xs-4 col-sm-3 col-md-2 col-lg-1">
<input type="submit" class="btn btn-default" value="Search">
</div>
<div class="what-to-search hidden-11 col-sm-11 col-sm-offset-1">
<div class="checkbox">
<label>
<input type="checkbox" value="true" name="WhatToSearch" id="WhatToSearch">
NewsManager Search Only
</label>
</div>
</div>
</div>
</form></div>
So the SearchPhrase and WhatToSearch id's are duplicated.
Is there any way to work around this, or is there a better way to render the form elements to avoid this issue?
You could specify your own ID for the items, and then you wouldn't have this ID collision problem. Have you tried setting the id manually: Html.TextBoxFor( ... , new { id = "AnythingHere" }), where the id could be a freshly generated Guid? (Note that you'd probably need to add a prefix, because Guids can start with a number.
So you can use the following. The Guid doesn't look good, and is unnecessarily long. You might want to go with something shorter, like short guid, DateTime.Ticks, ...
#{
var id = "chk_" + Guid.NewGuid().ToString();
}
#Html.CheckBoxFor(..., new { id = id })
#Html.LabelFor(..., new { #for = id })

Handle button clicks in a .NET MVC application/ calling a controller from a cshtml page

I am working on a MVC web application and not sure where I should add my code to handle button clicks. I have a cshtml view that is being rendered by a controller. When the view is displayed I need to handle several buttons that are being displayed - such print, email, etc. Where should I add my code to handle these and can you give me an example on how to implement it?
<input id="save-button" type="submit" class="btn btn-primary" onclick="submitOrder();" value="Print Order" />
The submitOrder() call is what I need to handle.
1.If your button is not posting back to a form you can call the controller like this:
<input type="button" value="Something" onclick="location.href='#Url.Action("ActionName", "ControllerName")'" />
there are several overloads to this method, some accepting many more parameters.
2.If you are posting back a form and your input button is within that form, then your input button will post back to the controller.
The login page in the default mvc application has examples of both of the 2 options I've mentioned above.
Here's a part of that page:
<section id="loginForm">
#using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Use a local account to log in.</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(m => m.UserName, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.UserName, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.UserName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Password)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
#Html.CheckBoxFor(m => m.RememberMe)
#Html.LabelFor(m => m.RememberMe)
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Log in" class="btn btn-default" />
</div>
</div>
<p>
#Html.ActionLink("Register", "Register") if you don't have a local account.
</p>
}
</section>
You also have several options to call a controller using JQuery Ajax. That's a little more sophisticated, though.

Categories