I need to send a string to the controller then send result back to View in MVC.net - model-view-controller

I am trying to make an web app with MVC.Net to display text boxes in the view where a vmware hostname is entered then the value is taken from the box from a button click and sent to the controller which then searches for it using an external SQL server with the resulting vcenter sent back to the text box. Right now I have the SQL working with a statically entered host name (test1) , so I click on the button and it does return the vcenter from sql, but I need to know how to be able to have the value sent back from the text box from the view to the controller, then the result sent back to the view, please help. I find this MVC ridiculously convoluted and difficult especially compared to asp.net webforms.
I have the following code for the view
#{
#model getdata
<script type="text/javascript">
function Hello() {
var yourJavaScriptArray = #Html.Raw(Json.Serialize(Model.Name));
ResourcePool.value = "Hello!";
ipnumber.value = yourJavaScriptArray;
}
</script>
<tr>
<td><b>vCenter Name: </b></td>
<td> #Html.TextBox("vCenter", " ", new { style = "color:blue" })</td>
<td><input type="submit" value="TestQuery" button style=" width:140px;" onclick="Hello()" /></td>
</tr>
Then the model is simple -
namespace WebApplication1.Models
{
public class getdata
{
public string Name { get; set; }
public string read1 { get; set; }
public string textfrombox { get; set; }
public string searchText1 { get; set; }
}
}
Then for the controller -
[HttpPost]
public ActionResult Search(string searchText)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["sqlconnection"].ConnectionString);
var model = new Models.getdata();
string test1 = " HostName " ;
string textToQuery = "%" + test1.Trim() + "%";
string hosttest = ("select vcenter from db_owner.host where name like #textToQuery");
SqlCommand cmdhosts = new SqlCommand(hosttest, conn);
conn.Open();
cmdhosts.Parameters.AddWithValue("#textToQuery", textToQuery);
using (SqlDataReader read = cmdhosts.ExecuteReader())
{
while (read.Read())
{
// model.read1 = (read["Name"].ToString().Trim());
model.read1 = (read["Name"].ToString().Trim());
}
}
conn.Close();
model.Name = model.read1;
model.searchText1 = model.read1;
return View(model);
// return View(name);
}

Related

ASP.Net MVC Paging returns one large resultset instead of splitting resultset into pages

I am using Paging in my View and originally my #model was of type PagedList.IPagedList but I was having issues posting back the IPagedList interface back to controller, therefore, I found a post that gave a hint on how to deconstruct my IPagedList so I could present it in the View and be able to post back to controller for further processing as well. However, I ran into the following issue - I want to display only 50 records on each page. The search criteria I am testing returns 13000 records. I am expecting only 50 records on first page with page numbers 1,2,3 at bottom. I see the page numbers as expected at the bottom but all 13000 records get displayed on every page. I have debugged the code and found out that StaticPagedList function is returning 13000 records instead of 50 so I applied Skip and Take on the object before returning it to the View but the issue is still occurring. My code:
View Models -
public class PagedClientViewModel
{
public int? Page { get; set; }
public IEnumerable<SelectTimeTrackerEditorViewModel> Clients { get; set; }
public IPagedList PagingMetaData { get; set; }
}
public class SelectTimeTrackerEditorViewModel
{
public bool Selected { get; set; }
public int SID { get; set; }
public string PerNo { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
View -
#model EmergencyResponseTimeEntry.Models.PagedClientViewModel
#using PagedList;
#using PagedList.Mvc;
#foreach (var item in Model.Clients)
{
<tr>
<td>
#Html.CheckBoxFor(modelItem => item.Selected)
</td>
<td>
#Html.DisplayFor(modelItem => item.PerNo)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
</tr>
}
Page #(Model.PagingMetaData.PageCount < Model.PagingMetaData.PageNumber ? 0 : Model.PagingMetaData.PageNumber) of #Model.PagingMetaData.PageCount
#Html.PagedListPager(new StaticPagedList<EmergencyResponseTimeEntry.Models.SelectTimeTrackerEditorViewModel>(Model.Clients, Model.PagingMetaData), page => Url.Action("Index", new { page }), new PagedListRenderOptions { DisplayEllipsesWhenNotShowingAllPageNumbers = false})
Controller -
var list = (from c in timeTrackers
select new SelectTimeTrackerEditorViewModel
{
Selected = false,
SID = c.SID,
PerNo = c.PerNo,
FirstName = c.FirstName,
LastName = c.LastName
});
var pagedClientViewModel = new PagedClientViewModel
{
Clients = list
};
int pageSize = 50;
int pageNumber = (page ?? 1);
int totalClients = list.Count();
// List of current page of 50 records (hits database again, pulls only 50 records, though)
var timeTrackerList = list.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToList();
pagedClientViewModel.PagingMetaData = new StaticPagedList<SelectTimeTrackerEditorViewModel>
(timeTrackerList, pageNumber, pageSize, totalClients).GetMetaData();
return View(pagedClientViewModel);
I got it working after co-worker pointed out that I was displaying all records in my view - Model.Clients. So in my controller, I changed this
var pagedClientViewModel = new PagedClientViewModel
{
Clients = list
};
to this -
var pagedClientViewModel = new PagedClientViewModel
{
Clients = list.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToList()
};
Now paging is working as expected!

Using UniDynArray on ASP.net MVC view page

Can anyone help me on how to use UniDynArray on ASP.net MVC3 (MS Visual Studio 2010) View Page?
I managed to add reference (U2.Data.Client) to the project and I'm able to use it in the Controller, but not in View page.
The reason to utilize the UniDynArray is that, I would like to pass a dynamic array from Controller to View and back to controller. This way I will not have to set every field to VIEWDATA in order to be use in View.
I would like to explain how to pass UniDynArray to MVC View from Controller the following ways:
MVVM Pattern (Raw UniDynArray)
ViewBag Pattern (Raw UniDynArray)
MVVM Pattern (flatten UniDynArray, UniDynArray to .NET Object DataTable)
MVVM Pattern (flatten UniDynArray, UniDynArray to POCO Object)
In this post , I will answer MVVM Pattern (Raw UniDynArray). Later I will cover rest.
Create ASP.NET MVC3 Project
Create a Model
Add a controller
Create a View
Open ‘CustomerViewModel.cs’ file and paste the following code
namespace Test_MvcApplication.Models
{
public class CustomerViewModel
{
public Customer MyCustomer { get; set; }
public CustomerViewModel(Customer pCustomer)
{
MyCustomer = pCustomer;
}
}
public class Customer
{
private UniDynArray myVar;
public UniDynArray MyUniDynArray
{
get
{
U2ConnectionStringBuilder conn_str = new U2ConnectionStringBuilder();
conn_str.UserID = "user";
conn_str.Password = "pass";
conn_str.Server = "localhost";
conn_str.Database = "HS.SALES";
conn_str.ServerType = "UNIVERSE";
conn_str.AccessMode = "Native"; // FOR UO
conn_str.RpcServiceType = "uvcs"; // FOR UO
conn_str.Pooling = false;
string s = conn_str.ToString();
U2Connection con = new U2Connection();
con.ConnectionString = s;
con.Open();
Console.WriteLine("Connected.........................");
// get RECID
UniSession us1 = con.UniSession;
UniSelectList sl = us1.CreateUniSelectList(2);
// Select UniFile
UniFile fl = us1.CreateUniFile("CUSTOMER");
fl.RecordID = "2";
myVar = fl.Read();
return myVar;
}
set
{
myVar = value;
}
}
}
}
Open ‘MyUniDynArrayController.cs’ and paste the following code. As you notice that you are passing object to view and that object has UniDynArray
namespace Test_MvcApplication.Controllers
{
public class MyUniDynArrayController : Controller
{
//
// GET: /MyUniDynArray/
public ActionResult Index()
{
Customer c = new Customer();
UniDynArray r = c.MyUniDynArray;
var l = new CustomerViewModel(c);
return View(l);
}
}
}
Open ‘MyUniDynArray\ Index.cshtml’ and paste the following code. #Model contains ViewModel object (UniDynArray)
#{
ViewBag.Title = "Index";
}
MyUniDynArray
==================
#Model.MyCustomer.MyUniDynArray
Open ‘Shared\Layout.cshtml’ file and add the following line
<nav>
<ul id="menu">
<li>#Html.ActionLink("MyUniDynArray", "Index", "MyUniDynArray")</li>
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
</ul>
</nav>
Run the application and press ‘MyUniDynArray’. You will see UniDynArray in View. I am not sure how are you going to bind UniDynArray with HTML5/Razor Controls. That’s why I sugest you to flatten UniDynArray.
Typed UniDynArray in MVC View
In this post , I would like to describe 'MVVM Pattern (flatten UniDynArray, UniDynArray to .NET Object Object) '.
Create a Model
Create Controller
Create View
Open Model file (Models\CustomerViewModel2.cs) and paste the coode
namespace Test_MvcApplication.Models
{
public class Customer2
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime HireDate { get; set; }
}
public class Customer2Repository
{
private List<Customer2> m_custList = new List<Customer2>();
public List<Customer2> CustomerList
{
get
{
U2ConnectionStringBuilder l = new U2ConnectionStringBuilder();
l.Server = "localhost";
l.UserID = "user";
l.Password = "pass";
l.Database = "HS.SALES";
l.ServerType = "universe";
string lconnstr = l.ToString();
U2Connection c = new U2Connection();
c.ConnectionString = lconnstr;
c.Open();
U2Command command = c.CreateCommand();
command.CommandText = "CALL MV_TO_DATASET_SELECT_SUBROUTINE(?,?)"; // UniVerse subroutine
command.CommandType = CommandType.StoredProcedure;
U2Parameter p1 = new U2Parameter();
p1.Direction = ParameterDirection.InputOutput;
p1.Value = "";
p1.ParameterName = "#arg1";
U2Parameter p2 = new U2Parameter();
p2.Direction = ParameterDirection.InputOutput;
p2.Value = "";
p2.ParameterName = "#arg2";
command.Parameters.Add(p1);
command.Parameters.Add(p2);
command.ExecuteNonQuery();
string lRetValue = (string)command.Parameters[1].Value;
//command.Parameters[1].MV_To_POCO<int>();
m_custList = command.Parameters[1].MV_To_POCO<Customer2>();
return m_custList;
}
set
{
m_custList = value;
}
}
}
public class CustomerViewModel2
{
public Customer2 MyCustomer2 { get; set; }
public List<Customer2> CustomerList { get; set; }
public CustomerViewModel2(Customer2 pCustomer)
{
MyCustomer2 = pCustomer;
}
public CustomerViewModel2(List<Customer2> pCustomerList)
{
CustomerList = pCustomerList;
}
}
}
Open Controller file (Controllers\MyUniDynArray2Controller.cs)
namespace Test_MvcApplication.Controllers
{
public class MyUniDynArray2Controller : Controller
{
//
// GET: /MyUniDynArrayController2/
public ActionResult Index()
{
Customer2Repository lvar = new Customer2Repository();
List<Customer2> lCustomer2List = lvar.CustomerList;
var l = new CustomerViewModel2(lCustomer2List);
return View(l);
}
}
}
Open View File (Views\MyUniDynArray2\Index.cshtml)
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<table border="1">
<tr>
<td>ID</td>
<td>Name</td>
<td>HireDate</td>
</tr>
#foreach (var myItem in Model.CustomerList)
{
<tr>
<td>#myItem.ID</td>
<td>#myItem.Name</td>
<td>#myItem.HireDate</td>
</tr>
}
</table>
Open ‘Shared\Layout.cshtml’ file and add the following line
<nav>
<ul id="menu">
<li>#Html.ActionLink("MyUniDynArray2", "Index", "MyUniDynArray2")</li>
<li>#Html.ActionLink("MyUniDynArray", "Index", "MyUniDynArray")</li>
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
</ul>
</nav>
Run the application and press ‘MyUniDynArray2’. You will see Flatten UniDynArray. Basically UniDynArray becomes array of .NET objects(List)
Used UniVerse Subroutine
SUBROUTINE MV_TO_DATASET_SELECT_SUBROUTINE(ARG_INPUT,ARG_OUTPUT)
x = ARG_INPUT
ARG_OUTPUT = "100":#VM:"101":#VM:"102":#VM:"103":#FM:"Nancy":#VM:"Andrew":#VM:"Janet":#VM:"Margaret":#FM:"01/06/1991":#VM:"06/07/1996":#VM:"11/08/1999":#VM:"12/10/2001"
RETURN

LINQ result is not showing as expected

I'm trying to query for a particular column & to show the item list in view properly one after another. Here is my code:
Controller:
public ActionResult ShowImage()
{
using (var context = new ImageTrialDBEntities())
{
var pathlist = (from s in context.Images
select s.ImageLink).ToList();
var model = new ImageModel();
model.ImageList = pathlist;
return View(model);
}
}
Model:
public class ImageModel
{
public string Image { get; set; }
public IList<string> ImageList { get; set; }
}
View:
<div>
#foreach (var s in Model.ImageList)
{
#Html.DisplayFor(x=>x.ImageList)
<br />
}
</div>
The list is showing like this:
I would like to show one at a time with a break in between. Please help.
Replace
#Html.DisplayFor(x=>x.ImageList)
with
#Html.DisplayFor(x=>s)
You have 2 loops in the view code. Try just printing out the variable s.

Cascading dropdown lists MVC3

Relatively new to MVC and trying to get a cascading dropdown list working for train times.
After looking at a lot of posts, people say that you should stay away from ViewBag/ViewData and instead focus on ViewModels, but I just can't seem to get my head round it, and it's driving me up the wall. Any tutorial seems to be either to complex or too easy and the whole viewModel idea just hasn't clicked with me yet.
So here is my scenario: I have an admin system where staff can add individual train journeys. For each train time, I have an input form where the user can choose a Company, and from there, I'd like the dropdownlist underneath to populate with a list of journey numbers, which indicate routes. Once they have chosen a number, they can carry on with the rest of the form, which is quite large, including time of travel, facilities on the train etc.
I've created a viewmodel like so:
public class JourneyNumbersViewModel
{
private List<SelectListItem> _operators = new List<SelectListItem>();
private List<SelectListItem> _journeys= new List<SelectListItem>();
[Required(ErrorMessage = "Please select an operator")]
public string SelectedOperator { get; set; }
[Required(ErrorMessage = "Please select a journey")]
public string SelectedJourney { get; set; }
public List<SelectListItem> Journeys
{
get { return _journeys; }
}
public List<SelectListItem> Operators
{
get
{
foreach(Operator a in Planner.Repository.OperatorRepository.GetOperatorList())
{
_operators.Add(new SelectListItem() { Text = a.OperatorName, Value = a.OperatorID.ToString() });
}
return _operators;
}
}
}
In my controller, I have this for the Create view:
public ActionResult Create()
{
return View(new JourneyNumbersViewModel());
}
And this is where it isn't really working for me - if I change my model at the top of the Create view to: #model Planner.ViewModels.JourneyNumbersViewModel, then the rest of my form throws errors as the model is no longer correct for the rest of the form. Is this the way it is supposed to work - what if you need to reference multiple view models with a single view?
I know this is a simple thing and as soon as it clicks I'll wonder how on earth I could have struggled with it in the first place, but if anyone can point out where I'm going wrong, I'd be very grateful.
I have done something similar. Here is some of the code (apologies upfront for this being quite long, but I wanted to make sure you could re-create this on your side):
View looks like this:
using Cascading.Models
#model CascadingModel
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Cascading Forms</h2>
<table>
#using(Html.BeginForm("Index", "Home"))
{
<tr>
<td>#Html.LabelFor(m=>m.CategoryId)</td>
<td>#Html.DropDownListFor(m => m.CategoryId, new SelectList(Model.Categories, "Id", "Name"), string.Empty)</td>
</tr>
<tr>
<td>#Html.LabelFor(m=>m.ProductId)</td>
<td>#Html.CascadingDropDownListFor(m => m.ProductId, new SelectList(Model.Products, "Id", "Name"), string.Empty, null, "CategoryId", "Home/CategorySelected")</td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="Go"/></td>
</tr>
}
</table>
the Model looks as follows:
public class CascadingModel
{
public int CategoryId { get; set; }
public List<Category> Categories { get; set; }
public int ProductId { get; set; }
public List<Product> Products { get; set; }
}
the real "clever" part of the system is the Html.CascadingDropDownListFor which looks as follows:
public static class MvcHtmlExtensions
{
public static MvcHtmlString CascadingDropDownListFor<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression,
IEnumerable<SelectListItem> selectList,
string optionLabel,
IDictionary<string, Object> htmlAttributes,
string parentControlName,
string childListUrl
)
{
var memberName = GetMemberInfo(expression).Member.Name;
MvcHtmlString returnHtml = Html.SelectExtensions.DropDownListFor(htmlHelper, expression, selectList, optionLabel, htmlAttributes);
var returnString = MvcHtmlString.Create(returnHtml.ToString() +
#"<script type=""text/javascript"">
$(document).ready(function () {
$(""#<<parentControlName>>"").change(function () {
var postData = { <<parentControlName>>: $(""#<<parentControlName>>"").val() };
$.post('<<childListUrl>>', postData, function (data) {
var options = """";
$.each(data, function (index) {
options += ""<option value='"" + data[index].Id + ""'>"" + data[index].Name + ""</option>"";
});
$(""#<<memberName>>"").html(options);
})
.error(function (jqXHR, textStatus, errorThrown) { alert(jqXHR.responseText); });
});
});
</script>"
.Replace("<<parentControlName>>", parentControlName)
.Replace("<<childListUrl>>", childListUrl)
.Replace("<<memberName>>", memberName));
return returnString;
}
private static MemberExpression GetMemberInfo(Expression method)
{
LambdaExpression lambda = method as LambdaExpression;
if (lambda == null)
throw new ArgumentNullException("method");
MemberExpression memberExpr = null;
if (lambda.Body.NodeType == ExpressionType.Convert)
{
memberExpr = ((UnaryExpression)lambda.Body).Operand as MemberExpression;
}
else if (lambda.Body.NodeType == ExpressionType.MemberAccess)
{
memberExpr = lambda.Body as MemberExpression;
}
if (memberExpr == null)
throw new ArgumentException("method");
return memberExpr;
}
}
Controller Logic for those looking for it:
public ActionResult CategoriesAndProducts()
{
var viewModel = new CategoriesAndProductsViewModel();
viewModel.Categories = FetchCategoriesFromDataBase();
viewModel.Products = FetchProductsFromDataBase();
viewModel.CategoryId = viewModel.Categories[0].CategoryId;
viewModel.ProductId = viewModel.Products.Where(p => p.CategoryId).FirstOrDefault().ProductId;
return View(viewModel);
}

MVC3 Display a dropdown list from one datasource and save to another datasource

I'm getting back to an MVC3 project after a 3 month hiatus. I need to display a drop down list that pulls from Database A, but saves to Database B. The property I need to persist is the NAICS/SIC code. Right now I just provide the user a text box to key in freeform text. So, I have the mechanics of that down. But instead it should provide only a valid list of codes from a source database.
The tricky thing to is I'm using a custom model binder to generate my ViewModels on the fly, so I don't have a distinct .cshtml file to customize.
[Serializable]
public class Step4ViewModel : IStepViewModel
{
public Step4ViewModel()
{
}
//load naics codes from somewhere
[Display(Name = "Describe the nature of your business.")]
public String NatureOfBusiness { get; set; }
[Display(Name="NAICS/SIC CODE")]
public String BusinessTypeCode { get; set; }
Tricky ViewModel
#using Microsoft.Web.Mvc;
#using Tangible.Models;
#model Tangible.Models.WizardViewModel
#{
var currentStep = Model.Steps[Model.CurrentStepIndex];
var progress = ((Double)(Model.CurrentStepIndex) / Model.Steps.Count) * 100;
}
<script type="text/javascript">
$(function () {
$("#progressbar").progressbar({
value: #progress
});
});
</script>
<div id="progressbar" style="height:20px;">
<span style="position:absolute;line-height:1.2em; margin-left:10px;">Step #(Model.CurrentStepIndex + 1) out of #Model.Steps.Count</span>
</div>
#Html.ValidationSummary()
#using (Html.BeginForm())
{
#Html.Serialize("wizard", Model)
#Html.Hidden("StepType", Model.Steps[Model.CurrentStepIndex].GetType())
#Html.EditorFor(x => currentStep, null, "")
if (Model.CurrentStepIndex > 0)
{
<input type="submit" value="Previous" name="prev" />
}
if (Model.CurrentStepIndex < Model.Steps.Count - 1)
{
<input type="submit" value="Save & Continue" name="next" />
}
else
{
<input type="submit" value="Finish" name="finish" />
}
#*<input type="submit" value="Save" name="Save" />*#
}
Controller
[HttpPost]
public ActionResult Index([Deserialize] WizardViewModel wizard, IStepViewModel step)
{
wizard.Steps[wizard.CurrentStepIndex] = step;
if (ModelState.IsValid)
{
//Always save.
var obj = new dr405();
//wire up to domain model;
foreach (var s in wizard.Steps)
{
Mapper.Map(s,obj,s.GetType(), typeof(dr405));
}
using (var service = new DR405Service())
{
//Do something with a service here.
service.Save(db, obj);
}
if (!string.IsNullOrEmpty(Request["next"]))
{
wizard.CurrentStepIndex++;
}
else if (!string.IsNullOrEmpty(Request["prev"]))
{
wizard.CurrentStepIndex--;
}
else
{
return View("Upload", obj);
}
}
else if (!string.IsNullOrEmpty(Request["prev"]))
{
wizard.CurrentStepIndex--;
}
return View(wizard);
}
WizardViewModel
[Serializable]
public class WizardViewModel
{
public String AccountNumber { get; set; }
public int CurrentStepIndex { get; set; }
public Boolean IsInitialized { get { return _isInitialized; } }
public IList<IStepViewModel> Steps { get; set; }
private Boolean _isInitialized = false;
public void Initialize()
{
try
{
Steps = typeof(IStepViewModel)
.Assembly.GetTypes().Where(t => !t.IsAbstract && typeof(IStepViewModel).IsAssignableFrom(t)).Select(t => (IStepViewModel)Activator.CreateInstance(t)).ToList();
_isInitialized = true;
//rewrite this. get the profile and wire them up or something.
this.AccountNumber = Tangible.Profiles.DR405Profile.CurrentUser.TangiblePropertyId;
}
catch (Exception e)
{
_isInitialized = false;
}
}
}
You can specify a template for a specific property on your view model by adding the UIHint attribute to the field. Since your view calls EditorFor on the model it will use the template you specified with UIHint.
BusinessTypeDropdown.ascx - (placed in Views/Shared/EditorTemplates
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>
<% var businessTypes = ViewData["businessTypes"] as IEnumerable<string>; %>
<%= Html.DropDownListFor(m => m , new SelectList(businessTypes, Model))%>
In your View Model
[Serializable]
public class Step4ViewModel : IStepViewModel
{
public Step4ViewModel()
{
}
//load naics codes from somewhere
[Display(Name = "Describe the nature of your business.")]
public String NatureOfBusiness { get; set; }
[Display(Name="NAICS/SIC CODE")][UIHint("BusinessTypeDropdown")]
public String BusinessTypeCode { get; set; }
Then in your controller just set ViewData["businessTypes"] to your list of business types.
Without understanding your "tricky" view model code, it will be hard to make helpful suggestions.
However, there shouldn't be much problem here. You need to somehow create your dropdown list in yoru view, and populate it from data passed from your controller.
All the work happens in your controller. Populate your list or IEnumerable or whatever data source from your first database, then in your post handler save the selection it to your second database (the second part should not be much different from what you already have).

Resources