Pass an array to the view using viewbag - asp.net

I have a code where I used checkbox in order for the user to choose his preferences.
Here is the code in my controller.
[HttpPost]
public ActionResult Selected_Softwares(string[] type){
var results = db.Softwares_Reports_vw.Where(s => type.Contains(s.software_name)).OrderBy(s=>s.software_name);
//here i tried to pass the parameter to viewbag
ViewBag.type = type;
return PartialView(results);
}
In my view:
<span style="float:right"> <input type="button" style="border: 2px groove #FBF5EF; background-color:ActiveCaption;"
class="my-button" value="Export Data To Excel" name="back"
onclick="#("location.href='" + Url.Action("toExcel_Results2", "Softwares", new { softwares = ViewBag.type }) + "'")" /> </span>
And in my controller for the excel reports:
public ActionResult toExcel_Results2(string[] softwares)
{
Response.AddHeader("Content-Type", "application/vnd.ms-excel");
return View(db.Softwares_Reports_vw.Where(s => softwares.Contains(s.software_name)).OrderBy(s=>s.software_name);
}
But the parameter here had no value. Why? Any help is greatly appreciated.

If you look at the HTML (in the browser F12 tools) for the button labeled "Export Data To Excel" in your Softwares\Selected_Softwares view, you'll see something like this (look at the onclick event):
<input type="button" style="border: 2px groove #FBF5EF;
background-color:ActiveCaption;" class="my-button"
value="Export Data To Excel" name="back"
onclick="location.href='/Softwares/toExcel_Results2?softwares=System.String[]'">
Notice that the object that you put into your ViewBag (a string[]) simply is getting serialized in the HTML as literally "System.String[]". This is because all ASP.NET MVC does is call ToString() on that object. When you call ToString() on a string[], you get the string "System.String[]".
Here's what I would recommend... you seem to be wanting to send some data to your "toExcel_Results2" action. This usually indicates that you want a POST rather than a GET. Here's a fairly simple solution. Just change your Selected_Softwares view to include this:
#using (Html.BeginForm("toExcel_Results2", "Softwares", FormMethod.Post, new { id = "MyForm" }))
{
<span>
<input type="button" style="border: 2px groove #FBF5EF; background-color:ActiveCaption;"
class="my-button" value="Export Data To Excel" name="back"
onclick="document.getElementById('MyForm').submit();" />
#for (int i = 0; i < ViewBag.type.Length; i++)
{
#Html.Hidden("softwares[" + i.ToString() + "]", (string)ViewBag.type[i]);
}
</span>
}
With this, you'll find that your "toExcel_Results2" action is able to receive the full array of strings.

Related

Spring - same mapping to display different list

I'm trying to use the same view to display different lists based on the param I'm passing from the button in JSP.
what I need is: when user click on button, will call the same view but data should be display from the second list .(getPreviousYearReports())
here's my code:
#RequestMapping(value = "/viewReports.do", method = {RequestMethod.GET , RequestMethod.POST})
public ModelAndView viewReports( #RequestParam final Integer storeNumber,
final HttpServletRequest request) {
ModelAndView view = getModelAndView("viewReports");
List<StoreReport> reportsList;
if(request.getParameter("previous") != null ) {
reportsList = storeReportService.getPreviousYearReports(storeNumber);
} else {
reportsList = storeReportService.getReportsByStore(storeNumber);
}
....
}
in my JSP.
I have added submit button to call the same view mapping
<button id="previous" name="previous" type="submit" class="btnFwd gradient smButtonStyling"
onClick="window.location.href='/viewReports.do?storeNumber=${storeNumber}'">
View Previous Year Reports
I was missing to pass the "&previous" param
<button id="previous" name="previous" type="submit" class="btnFwd gradient smButtonStyling"
onClick="window.location.href='/StoreReports/viewReports.do?storeNumber=${storeNumber}&previous'">
View Previous Year Reports
</button>

knockout.js How to get values from form and get additional data ASP.NET MVC

What i got is:
var post = function(id, message, username, date) {
this.id = id;
this.message = message;
this.username = username;
this.date = date;
this.comments = ko.observableArray([]);
this.addComment = function(context) {
var comment = $('input[name="comment"]', context).val();
if (comment.length > 0) {
$.connection.boardHub.server.addComment(this.id, comment, vm.username())
.done(function() {
$('input[name="comment"]', context).val('');
});
}
};
And View:
<form class="add-comment" data-bind="submit: addComment">
<div class="row">
<div class="col-md-9">
<input type="text" class="form-control" name="comment" placeholder="" />
</div>
<div class="col-md-3">
<button class="btn btn-default" type="submit">Answer</button>
</div>
And the question is how can i pass to addComment extra value without missing context?
Like:
<form data-bind="submit: function(){ writePost(<context>, '#ViewBag.UserN'); }">
As I mentioned in my comment, you are not using knockout correctly. Therefore I'll provide you with a generic example of how you should handle form submits using knockout.
First, you should define a viewmodel which wraps your UI data and connects to services to do any actual logic. In simple cases, many people just write the logic, such as API calls right into the viewmodel instead of a service. For simplicity, I'll just do that, because extracting it into its own 'class' should be simple enough. You should give your viewmodel a more descriptive name than post. Here is an example:
var commentViewModel = function(id, userName) {
var self = this;
this.commentText = ko.observable('');
this.addComment = function() {
var txt = self.commentText();
if (txt) {
$.connection.boardHub.server.addComment(id, txt, userName)
.done(function() {
self.commentText('');
});
}
};
};
var commentVM = new commentViewModel('#ViewBag.Id', '#ViewBag.UserN');
$(function() { ko.applyBindings(commentVM); });
HTML:
<form class="add-comment" data-bind="submit: addComment">
<div class="row">
<div class="col-md-9">
<input type="text" class="form-control" data-bind="textInput: commentText" />
</div>
<div class="col-md-3">
<button class="btn btn-default" type="submit">Answer</button>
</div>
</div>
</form>
Explaination:
The commentVM object contains a commentText member. This is a KO observable, so by exposing it by assigning it to this, you can bind to it. Then you can read the value of it by utilizing the KO binding mechanism instead of mixing jQuery and KO. Bindings exist to simplify your life not to be mixed with plain jQuery stuff, so you should use them wherever you can.
You should also expose an observable array to hold the actual comments, but since that wasn't part of your question I didn't want to introduce it to exclude any additional noise which is not related to what you asked.
In your HTML, you used the submit binding correctly. By binding the submit event to the addComment method, this method will get invoked correctly. But what's different compared to your code is that you read the comment text from the observable you've just defined, and avoid using jQuery. Since the VM itself is the context, you don't have to care about how to pass it -- that is, anything that you intend do use from within the submit method should generally be included in the viewmodel.
If, for whatever reason, you need to pass any extra parameter - such as dynamic content generated by Razor, for example, you can use the bind method. You can read more about it here, it is written just above Note 3. I'd like to note that even though it is documented in the click binding page, you can use it with submit as well (in fact, with any binding that binds to a method). Just for clarity, I'll include the relevant part here as well:
<button data-bind="click: myFunction.bind($data, 'param1', 'param2')">
Click me
</button>
So all you have to do is to specify the function to which you want to bind, and append a .bind($data, parameter1, parameter2,....) expression to it. Note that here, $data is the context; you should always include it in the .bind call. However, this will not be passed to any method parameter, it is necessary for KO to do its magic, so if you had a function like this:
function a(x,y,z)
then x would be passed param1, y would be passed param2 and z wouldn't be passed anything. If you want to force passing $data, you should include it twice in the bind call as such: .bind($data, $data, ....more params).

Which one is better or both are same?

I have a form which has 2 buttons "Delete" and "Edit".. on Post to check which button submitted the request... which of the 2 approaches is better and is there is any difference or both are same?
#if(isPost){
if(!Request["buttonDelete"].IsEmpty()){
//Do something
}
if(Request["btn"].Equals("buttonDelete")){
//do something
}
}
lets say you have html like this
<form method="post">
<input type="text" name="txtName" value="Vishal" />
<input type="submit" name="btnEdit" value="Edit" />
<input type="submit" name="btnDelete" value="Delete" />
</form>
here two buttons are there having edit and delete action. now when you submit a form on a server side you can have clicked element under form collection paramerters that you can access like
Request.Params["btnDelete"]
Request.Params["btnEdit"]
whichever element is clicked , the other element will be null
Request.Params["btnEdit"] will become null when you click on Delete button
same way Request.Params["btnDelete"] will become null when you click on Edit button
you can check like
if (!string.IsNullOrEmpty(Request.QueryString["Edit"]))
{
// do edit
}
hope that helps ! :)
If this is ASP MVC then both of this approaches are not correct. You must have separated actions for Save and Edit:
public ActionResult Edit(Entity item){
// do stuff
return RedirectToAction('Index', new { lastAction = 'Edit' });
}
public ActionResult Save(Entity item){
// do stuff
return RedirectToAction('Index', new { lastAction = 'Delete' });
}
Then, on Index view you may check 'lastAction' parameter:
#{
if(!Request.Params["lastAction"] == "Delete"){
//do something
} else if(Request["lastAction"] == "Edit"){
//do something
}
}

Asp.net MVC cancel button with multiple redirect choices

I currently have a form with a submit and cancel button. Depending on some logic, each time the page loads, I want that same cancel button to redirect to different other pages in the application. This is the code I have at the moment in my aspx view that changes the location.href based on my property
<% if (Model.MyProperty.Equals("something"))
{ %>
<input class="btnCancel" type="button" value="" onclick="location.href='<%: Url.Action("MyAction","MyController", new {Area="MyArea"},null)%>'" />
<% } %>
<% else if (Model.MyProperty.Equals("somethingelse"))
{ %>
<input class="btnCancel" type="button" value="" onclick="location.href='<%: Url.Action("MyOtherAction","MyOtherController", new {Area="SomeOtherArea"},null)%>'" />
<% } %>
Is this the correct and elegant way to do this? I would rather reduce the multiple IF-ELSE conditions if there was a way to do it.
Thanks for your time.
The way I've always handled multiple redirect options is by setting the href value in the controller action.
The View is generic, but the controller action is specific to the context of the page your rendering. So in your model, make a property called CancelUrl. Now, in the controller action, set it to the link you want it to go to.
model.CancelUrl = Url.Action("action", "controller");
This way, all you have to do in your View is say
Text
You can create a cancel method that takes your property as a parameter and redirect appropriately within the controller. This logic should probably not be in your view anyway as views should have almost 0 logic anyway
I would put the property that will be used to decide the cancel action in the view model (as you already have), alongside any other required properties.
For example:
public class IndexModel
{
//any other properties you need to define here
public string MyProperty { get; set; }
}
Then your view would look similar to:
#model IndexModel
#using (Html.BeginForm())
{
//other information you may want to submit would go here and in the model.
#Html.HiddenFor(m => m.MyProperty)
<button type="submit" name="submit" value="submit">submit</button>
<button type="submit" name="cancel" value="cancel">cancel</button>
}
And finally, your post action should decide the next action that should be returned:
[HttpPost]
public ActionResult Index(IndexModel model)
{
if (!string.IsNullOrEmpty(Request["submit"]))
{
if (ModelState.IsValid)
{
//any processing of the model here
return RedirectToAction("TheNextAction");
}
return View();
}
if (model.MyProperty.Equals("something"))
{
return RedirectToAction("MyAction", "MyController", new { area = "MyArea" });
}
else //assumes the only other option is "somethingelse"
{
return RedirectToAction("MyOtherAction", "MyOtherController", new { area = "SomeOtherArea" });
}
}

Styling HTML helpers ASP.NET MVC

If I have an HTML helper like so:
Name:<br />
<%=Html.TextBox("txtName",20) %><br />
How do I apply a CSS class to it? Do I have to wrap it in a span? Or do I need to somehow utilize the HtmlAttributes property of the helper?
You can pass it into the TextBox call as a parameter.
Name:<br/>
<%= Html.TextBox("txtName", "20", new { #class = "hello" }) %>
This line will create a text box with the value 20 and assign the class attribute with the value hello. I put the # character in front of the class, because class is a reserved keyword. If you want to add other attributes, just separate the key/value pairs with commas.
This is how to add a class and a style on the same element...
"x" being the model passed to the view with a property of TextBoxID
#Html.TextBoxFor(x => x.TextBoxID, new { #class = "SearchBarSelect", style = "width: 20px; background-color: green;" })
I did some research and came across this article that seems to have a solution to your question.
Ajax Control Toolkit with ASP.NET MVC#
source: jimzimmerman
ARTICLE LINK
http://www.ajaxprojects.com/ajax/tutorialdetails.php?itemid=330
QUOTE
So basically if you put the class name
TextboxWatermark on any textbox input
with the title you like to show as the
watermark like this:
<input type="text" class"TextboxWatermark" name="username" id="username" title="Must be at least 6 chars" />
or
<%= Html.TextBox("username", new { #class = "TextboxWatermark", #title = "Must be at least 6 chars" }) %>
What is nice about the second option
is that you get the added benefit of
getting the View Engine to fill out
the value of the textbox if there is
an item in ViewData of the
ViewData.Model that has a var named
'username'.
Use the htmlAttributes parameter with an anonymous type, like tihs:
<%=Html.TextBox("txtName","20", new { #class = "test"}) %>
the helper implementation
public static class LabelExtensioncs
{
public static MvcHtmlString Alarm(this HtmlHelper helper, string target, string text)
{
return MvcHtmlString.Create(string.Format("<p class='alert' style='background-color: #b8f89d;border-radius: 5px;width: 100%;'><b>{0}</b><br /><i>{1}</i></p>", target, text));
}
}
the usage in view section
#Html.Alarm("Title", "please unsure your card no is invisible in your authorized information")
the result
Theres no need to use span, because its not dynamic.
Css:
.testClass {
color: #1600d3;
}
View (Index):
#Html.TextBox("expression", "Text to show.", new { #class = "testClass" })
if you need dynamic options you can use for example:
CSS:
.test class{
background: #ffffff;
}
Controller (Index for test):
[HttpGet]
public ActionResult Index()
{
ViewBag.vbColor = "#000000";
return View();
}
View (Index):
<div>
<span>
#Html.TextBox("expression", "Text to show.", new
{ #class = "testClass", #style="color: " +
#ViewBag.vbColor })
</span>
</div>
Hope it helps.
Is it that much more work?

Resources