Using UniDynArray on ASP.net MVC view page - asp.net-mvc-3

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

Related

Is it possible to pass variables from the controller to the view and create multiple different URLs?

I have only recently begun using MVC. I have a situation in my view where I need to create several different links to several different places. Currently I am using a switch statement using their type as a parameter, and writing them out individually. Example here:
switch (link.Type)
{
case "type1": %>
<a href='<%= Url.RouteUrl("A", new { controller = "Controller1", action = "Action1",
param1 = x, param2 = y, newWindow = "yes" }) %>' target="_blank"><%: link.Name %></a> <%
break;
case "type2": %>
<a href='<%= Url.RouteUrl("B", new { controller = "Controller2", action = "Action2",
param1 = x, param2 = y, newWindow = "yes" }) %>' target="_blank"><%: link.Name %></a> <%
break;
}
As you can see from the example above, there are only very minor changes between the URLs. I believe I will have 10-20 of these types, and obviously solution where I would only have this once on the page would be ideal.
Is it possible to pass in variables to replace "A", "Controller1", "Action1"?
EDIT1: Erik already nailed my question but out of curiosity, is it also possible to supply parameter names through variables as well? So instead of having a parameter called "param2" I could have "param2" or "param3" decided through a variable?
EDIT2:
x and y in the example are ints that the used when the Url.RouteUrl link is clicked.
So for example, I have my two parameters that are projectId and recordId in my application. When the user clicks a link they are taken to a different controller/view and proceed from there. projectId is consistent in all links, but sometimes instead of recordId it might be tableId, articleId, etc. Is there a way to deal with these different parameters?
MVC is a Acronym for Model, View and Controller. The Controller should more often then not, create a Model and pass it into the view:
So you might have a class like:
public class IndexViewModel
{
public string SomeString { get; set; }
public string Controller { get; set; }
public string Action { get; set; }
}
Then a controller like:
public ActionResult Index()
{
var model = new IndexViewModel();
model.SomeString = "A";
model.Controller = "Controller1";
model.Action = "Action1";
return View(model);
}
Then the view:
#model IndexViewModel
<a href='<%= Url.RouteUrl(Model.SomeString,
new { controller = Model.Controller,
action = Model.Action,
param1 = x, param2 = y, newWindow = "yes" }) %>'
target="_blank"><%: link.Name %></a>
Update 1: You can't assign a value to a class in the constructor/initializer of an anonymous class.
var myvar = new MyClass;
var myanon = new { x = 1, MyClass.Prop = 2 };
//------------------------^
// You can't do this, it doesn't make sense
Update 2: The UrlHelper.RouteUrl() Method has a number of overrides. Instead of trying to dynamically create an object for the signature RouteUrl(String, Object) use the signature RouteUrl(String, RouteValueDictionary):
model:
public class IndexViewModel
{
public string SomeString { get; set; }
public RouteValueDictionary RouteValues { get; set; }
}
controller:
public ActionResult Index()
{
var model = new IndexViewModel();
model.SomeString = "A";
model.RouteValues = new RouteValueDictionary();
model.RouteValues.Add("Controller", "Controller1");
model.RouteValues.Add("Action", "Action1");
model.RouteValues.Add("param1", x);
model.RouteValues.Add("param2", y);
return View(model);
}
view:
#model IndexViewModel
<a href='<%= Url.RouteUrl(Model.SomeString,
Model.RouteValues) %>'
target="_blank"><%: link.Name %></a>
public ActionResult Index()
{
var model = new IndexViewModel();
ViewBag.Link1="A";
ViewBag.Link2="B";
ViewBag.Link13"C";
ViewBag.Link3="D";
return View("ViewName",model);
}
Inside View
//.Link1
if(ViewBag.Link1)
{
}
if(ViewBag.Link2)
{
}
if(ViewBag.Link3)
{
}
if(ViewBag.Link4)
{
}

MVC3 RadioButtonFor value is not binded to the model

I have a MVC3 Razor form. It have a radiobutton list and some another text fields. When I press submit controller post action get the view model, which have all fields seted correctly, except RegionID.
Model:
namespace SSHS.Models.RecorderModels
{
public class CreateViewModel
{
...
public int RegionID { get; set; }
...
}
}
Controller:
namespace SSHS.Controllers
{
public class RecorderController : Controller
{
...
public ActionResult Create()
{
EntrantDBEntities db = new EntrantDBEntities();
List Regions = new List(db.Region);
List Schools = new List(db.School);
List Settlements = new List(db.settlement);
CreateViewModel newEntr = new CreateViewModel();
ViewBag.Regions = Regions;
ViewBag.Schools = Schools;
ViewBag.Settlements = Settlements;
return View(newEntr);
}
[HttpPost]
public ActionResult Create(CreateViewModel m)
{
EntrantDBEntities db = new EntrantDBEntities();
Entrant e = new Entrant()
{
FatherName = m.FatherName,
Lastname = m.LastName,
LocalAddress = m.LocalAddress,
Name = m.Name,
RegionID = m.RegionID,
PassportID = m.PassportID,
SchoolID = m.SchoolID,
SettlementID = m.SattlementID,
TaxID = m.TaxID,
};
db.Entrant.AddObject(e);
db.SaveChanges();
return RedirectToAction("Index");
}
}
View:
#model SSHS.Models.RecorderModels.CreateViewModel
#using SSHS.Models
#using (Html.BeginForm("Create", "Recorder", FormMethod.Post))
{
#foreach (Region item in ViewBag.Regions)
{
#Html.RadioButtonFor(m => m.RegionID, item.RegionID)
#Html.Label(item.RegionName) - #item.RegionID
}
...
...
}
The Create(CreateViewModel m) method gets data from all textboxes normaly, but RegionID always is 0.
How are you planning to fill radio button with int ? It have two states: checked and not. Could you tell us, what are you trying to do? Make radio group? Use bool for RadioButtonFor.
Added:
You need to write something like this: CheckboxList in MVC3.0 (in your example you will have radio buttons)

Display Template For Generics - View is not found

I have the following classes:
public class Widget
{
public string Name { get; set; }
}
GenericModel
public class GenericModel<T>
{
public List<T> Data { get; set; }
}
My Controller action is:
public ActionResult Simple()
{
var model = new GenericModel<Widget>()
{
Data = new List<Widget>
{
new Widget {Name = "a"}
}
};
return View(model);
}
And my view is:
#model MyApp.GenericModel<MyApp.Widget>
#{
ViewBag.Title = "Simple";
}
<h2>Simple</h2>
#Html.DisplayFor(m=>m)
I have a file called GenericModel.cshtml in Views/Shared/DisplayTemplate folder:
#model MyApp.GenericModel<MyApp.Widget>
<ul>
#for (int i = 0; i < Model.Data.Count; i++ )
{
<li>
#Html.EditorFor(m=> Model.Data[i].Name)
</li>
}
</ul>
This view can not be found. I see when I print out the name of the type of my model I get "GenericModel1". Seeing that, I renamed my template "GenericModel1.cshtml". This seems like a bit of a hack, is there an easier way to find this display template without resorting to this?
You have to set it in your viewstart:
#Code
Layout = "~/Views/Shared/DisplayTemplate.cshtml"
End Code
Note: The above is VB.
You can also pass it via your controller like this:
public ActionResult Simple()
{
var model = new GenericModel<Widget>()
{
Data = new List<Widget>
{
new Widget {Name = "a"}
}
};
return View("", "DisplayTemplate", model);
}

How to get results from database in asp.net mvc 3 using ADO.NET

I wrote model class which returns a List then i pass it to view, but when the page is requested the view call the model many times and then crash the page, here's my code please help me I am new to asp.net MVC
Model
public List<string> DoWork()
{
List<string> results = new List<string>();
using (SqlConnection con = new SqlConnection(#"Connection String Here"))
{
con.Open();
using (SqlCommand cmd = new SqlCommand(#"SELECT Column1 FROM Table1", con))
{
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
results.Add(rdr.GetString(0));
}
}
}
}
return results;
}
Controller
public ActionResult Index()
{
MyData data = new MyData();
return View(data);
}
View
<ul>
#for (int i = 0; i <#Model.DoWork().Count; i++)
{
<li>
#Model.DoWork()[i]
</li>
}
</ul>
The idea is that the DB layer and View layer should be separated.
This being said, you should get your DB entities in your controller action method, not in the view, and use a ViewModel pattern to spit it to the view.In your case, you have a simple view model, IEnumerable, but it can be any entity.
public ActionResult Index()
{
MyData data = new MyData();
IEnumerable<string> thelist = data.DoWork();
return View(thelist);
}
and in yout View, use the IEnumerable as your model, and loop though it , not calling the DB to fetch your data:
#model IEnumerable<string>
......
#foreach(string s in Model)
{
<li>#s<li>
}
You are calling the DoWork method each time you want to use a result...
Store the result in a variable, and use that, instead.
<ul>
#{ List<string> works = Model.DoWork(); }
#for (int i = 0; i < works.Count; i++)
{
<li>
#works[i]
</li>
}
</ul>

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