Category: HowTo

short tutorials

Five common mistakes for ASP.NET MVC accesing resources : css, js, images, ajax

This is a Razor /MVC5 variant of older post
http://msprogrammer.serviciipeweb.ro/2010/10/09/five-common-mistakes-for-asp-net-mvc-accesing-resources-css-js-images-ajax/

To have once for all the link to show to people, because too much makes the same error again and again. (From here – you can use ResolveUrl or Url.Content – it’s the same for me. I use ResolveUrl because I used first …)

Case 1 The image does not display

Please check you have the following :

 <img src="@Url.Content("~/Content/images/YOURIMAGE.jpg" )" alt="image" style="border:0" /> or 
 
<img src="~/Content/images/YOURIMAGE.jpg" alt="image" style="border:0" /> 

Case 2 The css does not show

Please check you have the following :

 @string.Format("<link href="{0}" type="text/css" rel="stylesheet" />", Url.Content("~/Content/your.css"))  

or

 <style type="text/css">
@import '@Url.Content("~/Content/your.css")';

</style>  
  <style type="text/css">
<link href='~/Content/your.css' type='text/css' rel='stylesheet' />

</style>  

Case 3 The js does not execute (undefined error)

3.1 Please check you have the following :

 <script type="text/javascript" src="@Url.Content("~/Scripts/yourjs.js")"></script> 

or

 <script type="text/javascript" src="~/Scripts/yourjs.js"></script> 

This should be either in _Layout.cshtml, or in the scripts section

 @section scripts {   } 

in your .cshtml file.
3.2 please check in browser console ( press F12 ) for any javascript error that code may have

Case 4 The js does execute in .cshtml page, but did not execute under js file

Please check you DO NOT have the following @something in the js file. The js file is not interpreted by the same engine as cshtml, so can not interpret asp.net tags. Instead , add a parameter to your function for each @ variable that you have. Simple example : Let’s say in cshtml you have :

 <script type=”text/javascript”>

function Generate(){

window.open('@Url.Action(“About”)’);
}

</script> 

and you call Generate() from .cshtml file. Now you want the same in a .js file. The function Generate will have a parameter instead of Razor variable

 function Generate(url){  window.open(url); } 

and call like this from .cshtml file:

 Generate('@Url.Action("About")'); 

Case 5 The ajax request gives you a 404 error.

Please ensure that you have

 @Url.Content("~/path”) 

and not

 /path 

when you call the Ajax URL

Bonus 1: T4MVC , http://mvccontrib.codeplex.com/releases

Bonus 2: Edit the project file and put <MvcBuildViews>true</MvcBuildViews>

( short url: http://bit.ly/asp5Mistakes)

7 rules of logging ( and 7 notes)

Those are my 7 rules for logging (you can read also the side note for every rule)

So here they are:

  1. Logging is good for developers, not for the user .
  2. You should not re-invent logging framework – just use one that exists in your programming language.
  3. The logging should not affect the usual behavior of the program.
  4. You should log everywhere there is a layer made by you (including GUI).
  5. If the software returns/throws a generic code for error,then he should log the concrete details of what happened and the time * although this should be automatically done by the logging framework).
  6. The logging should be easy to configure ( where to log, what to log ).
  7. The format in which are you logging should be easy to understand by an automatic text parser

Note 1: Corollary : Every software needs logging and this should be performed as good as possible , with all specific details to understand the problem.

Note 2 : Choose one that works well in multi-threaded application, has multiple outputs ( database, log file, console , others) and provides various levels of logging( at least debug, info , error). For   .NET : log4net, nlog .  Do re-invent the wheel – if you believe that you can make something better .

Note 3 :  For example logging a function that modifies some parameters or logging variable.ToString() and this throws the infamous “null reference”

Note 4 : See http://liddellj.com/2014/09/09/log-all-the-things 

Note 5 : For example, if you throw a generic exception “ Something bad happened “ in order to not bother the user with mundane details, you should log the primary error and the reason that you throw the generic exception

Note 6:  This means it is easy for DevOps to configure the software to not log into production the debug levels .

Note 7: See http://dev.splunk.com/view/logging-best-practices/SP-CAAADP6

5 Minutes .NET–Memory Cache

 

At https://youtu.be/BL5yo_p7x-E you can find the new video about caching in .NET with Memory Cache.

The code is:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Text;
using System.Threading.Tasks;

namespace MemoryCacheNet
{
    public static class GlobalData
    {
        static object lockMe = new object();

        public static List<string> CountryList()
        {
            string key = "countries";
            var data = MemoryCache.Default.Get(key) as List<string>;
            if(data == null)
            {
                lock (lockMe)
                {
                    data = MemoryCache.Default.Get(key) as List<string>;
                    if(data != null)
                    {
                        return data ;
                    }
                    data = CountryListFromDatabase();
                    var duration = DateTimeOffset.UtcNow.AddSeconds(5);
                    MemoryCache.Default.AddOrGetExisting(key,data,duration);
                   

                }
            }
            return data;
        }
        static List<string> CountryListFromDatabase()
        {
            Console.WriteLine("obtaining data from database");
            return new List<string>()
            {
                "Romania",
                "India",
                "USA"
                // add your country 😉
            };
        }
    }
}

and using from Console:

using MemoryCacheNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MemoryCacheDOS
{
    class Program
    {
        static void Main(string[] args)
        {
            var data = GlobalData.CountryList();
            Console.WriteLine(data.Count);

            Console.WriteLine("waiting 1 sec");
            Thread.Sleep(1000);
            data = GlobalData.CountryList();
            Console.WriteLine(data.Count);

            Console.WriteLine("waiting 5 sec");
            Thread.Sleep(5000);
            data = GlobalData.CountryList();
            Console.WriteLine(data.Count);

        }
    }
}

 

Other tutorials are:

5MinThrowVsThrowEx
5Min Usefull Attributes
5MinIValidatableObject
5MinAsyncException
5MinAsync
5Min iMacrosAHK
5min Zip
5MinPSR
5MinParseWebPage
5MinFileHelpers
5Min Logging
5min Send emails and SMTP4Dev
5Min Memory Profiler ( User Object and/or memory leaks)
5min SFHB
5min – .TT files in Visual Studio

The full list is at https://www.youtube.com/playlist?list=PL4aSKgR4yk4OnmJW6PlBuDOXdYk6zTGps  .

EF Record and play – conclusions

 

Part 1 : What is EF record and play : http://msprogrammer.serviciipeweb.ro/2014/11/29/entity-framework-6-record-and-play-1-of-5/ 

Part 2: EF Record and play use: Testing : http://msprogrammer.serviciipeweb.ro/2014/12/08/entity-framework-6-record-and-play-use-unit-testing-part-2-of-5/

Part 3: EF Record and play use: Make demo: http://msprogrammer.serviciipeweb.ro/2014/12/14/entity-framework-6-record-and-play-use-making-demos-part-3-of-5/ 

Part 4: EF Record and play use: Record user Sql when a bug occurs: http://msprogrammer.serviciipeweb.ro/2014/12/26/ef-record-and-play-use-recording-user-sql-when-a-bug-occurred-part-4-of-5/

Part 5: EF record and play: conclusions: http://msprogrammer.serviciipeweb.ro/2015/01/05/ef-record-and-play-conclusions/

 

 

I have show to you how easy you can record and play again Entity Framework 6 actions. Also, some possible uses as testing, making demos and record user Sql.

One possible use that can be done is Profiling  – analyzing sql – for example, just like MiniProfiler or EFProfiler does. Read this article about profiling : http://msdn.microsoft.com/en-us/magazine/gg490349.aspx

I hope you enjoy this piece of code.

Source code is available at https://github.com/ignatandrei/EFRecordAndPlay/wiki/
There is also a NuGet package at https://www.nuget.org/packages/EFRecordAndPlay/

Video at https://www.youtube.com/playlist?list=PL4aSKgR4yk4Mi1eLKArsgoqQRluxXv2-Y

EF Record and play use: Recording user sql when a bug occurred (part 4 of 5)

 

Part 1 : What is EF record and play : http://msprogrammer.serviciipeweb.ro/2014/11/29/entity-framework-6-record-and-play-1-of-5/ 

Part 2: EF Record and play use: Testing : http://msprogrammer.serviciipeweb.ro/2014/12/08/entity-framework-6-record-and-play-use-unit-testing-part-2-of-5/

Part 3: EF Record and play use: Make demo: http://msprogrammer.serviciipeweb.ro/2014/12/14/entity-framework-6-record-and-play-use-making-demos-part-3-of-5/ 

Part 4: EF Record and play use: Record user Sql when a bug occurs: http://msprogrammer.serviciipeweb.ro/2014/12/26/ef-record-and-play-use-recording-user-sql-when-a-bug-occurred-part-4-of-5/

Part 5: EF record and play: conclusions: http://msprogrammer.serviciipeweb.ro/2015/01/05/ef-record-and-play-conclusions/

 

In this video tutorial I will show how to see the sql when a database bug occurs.

Let’s suppose that a department should have the name not null – and , by mistake, we have not prevented the registering of a null in the name of the department

We put those lines

 
 #region set record EF
            record = new InterceptionRecordOrPlay(@"DemoEmployeeAndDepartment.zip", ModeInterception.Record);

            DbInterception.Add(record);
            #endregion 

We register the null name department and  in the DemoEmployeeAndDepartment.zip we see the error

<?xml version="1.0"?>
<InterceptionData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <CommandText>INSERT [Department]([NameDepartment])
VALUES (NULL)
; SELECT [Id]
FROM [Department]
WHERE [Id] = CAST (@@IDENTITY AS int)</CommandText>
  <NonQuery>0</NonQuery>
  <ThrownExc>
    <ExceptionType>System.Data.SqlServerCe.SqlCeException</ExceptionType>
    <ExceptionMessage>The column cannot contain null values. [ Column name = NameDepartment,Table name = Department ]</ExceptionMessage>
  </ThrownExc>
</InterceptionData>

Source code is available at https://github.com/ignatandrei/EFRecordAndPlay/wiki/
There is also a NuGet package at https://www.nuget.org/packages/EFRecordAndPlay/

Entity Framework 6 Record and play use : Making demos ( part 3 of 5)

 

Part 1 : What is EF record and play : http://msprogrammer.serviciipeweb.ro/2014/11/29/entity-framework-6-record-and-play-1-of-5/ 

Part 2: EF Record and play use: Testing : http://msprogrammer.serviciipeweb.ro/2014/12/08/entity-framework-6-record-and-play-use-unit-testing-part-2-of-5/

Part 3: EF Record and play use: Make demo: http://msprogrammer.serviciipeweb.ro/2014/12/14/entity-framework-6-record-and-play-use-making-demos-part-3-of-5/ 

Part 4: EF Record and play use: Record user Sql when a bug occurs: http://msprogrammer.serviciipeweb.ro/2014/12/26/ef-record-and-play-use-recording-user-sql-when-a-bug-occurred-part-4-of-5/

Part 5: EF record and play: conclusions: http://msprogrammer.serviciipeweb.ro/2015/01/05/ef-record-and-play-conclusions/

 

 

Let’s assume you want to register a demo for a application ( Desktop or Web).

You do arrange the database and you make some repetition before. However, the database must be re-arranged the next time you will make the demo.

For this case you can use EF 6 Record and play – it will make a .zip file with containing resultsets and you can make indefinitely the repetition of the demo – without the real database.

 

Let’s see in action here

 

 

The code is simple

 Database.SetInitializer<ContextForDatabase>(null);
            #region set record EF
            record = new InterceptionRecordOrPlay(@"DemoEmployeeAndDepartment.zip", ModeInterception.Play);

            DbInterception.Add(record);
            #endregion

Source code is available at  https://github.com/ignatandrei/EFRecordAndPlay/wiki/

There is also a NuGet package at https://www.nuget.org/packages/EFRecordAndPlay/

Entity Framework 6 Record and play use : Unit Testing ( part 2 of 5)

 

Part 1 : What is EF record and play : http://msprogrammer.serviciipeweb.ro/2014/11/29/entity-framework-6-record-and-play-1-of-5/ 

Part 2: EF Record and play use: Testing : http://msprogrammer.serviciipeweb.ro/2014/12/08/entity-framework-6-record-and-play-use-unit-testing-part-2-of-5/

Part 3: EF Record and play use: Make demo: http://msprogrammer.serviciipeweb.ro/2014/12/14/entity-framework-6-record-and-play-use-making-demos-part-3-of-5/ 

Part 4: EF Record and play use: Record user Sql when a bug occurs: http://msprogrammer.serviciipeweb.ro/2014/12/26/ef-record-and-play-use-recording-user-sql-when-a-bug-occurred-part-4-of-5/

Part 5: EF record and play: conclusions: http://msprogrammer.serviciipeweb.ro/2015/01/05/ef-record-and-play-conclusions/

 

Let’s suppose that we have a program that have Departments and Employees.

And we want to make sure that, when we add an employee, the department must exists.

We can ensure this from database ( by foreign key) but we can pro-actively search for the department and throw a more meaningful validation .

More, I like more validation than errors.

So, let’s suppose that in the Validation for the Employee we must check in the database for the IdDepartment to see if there is such a department.

How could we make a test for that runs without a database ?

With some trick:  we first Record with a database  – then we can Play the file – and we do not need anymore the database. The test is self contained. 

 

Let’s see in action here

 

Database.SetInitializer<ContextForDatabase>(null);
            #region set record EF
            var record = new InterceptionRecordOrPlay(@"VerifyIValidatableWorks.zip", ModeInterception.Play);

            DbInterception.Add(record);
            #endregion
            var e= new Employee();
            e.ValidateEmployee = true;
            e.IDDepartment = 60000;
            var err= e.Validate(null).ToArray();
            Assert.IsNotNull(err);
            Assert.AreEqual(1, err.Length);

Source code is available at  https://github.com/ignatandrei/EFRecordAndPlay/wiki/

 

There is also a NuGet package at https://www.nuget.org/packages/EFRecordAndPlay/

Entity Framework 6 Record and play – 1 of 5

 

Part 1 : What is EF record and play : http://msprogrammer.serviciipeweb.ro/2014/11/29/entity-framework-6-record-and-play-1-of-5/ 

Part 2: EF Record and play use: Testing : http://msprogrammer.serviciipeweb.ro/2014/12/08/entity-framework-6-record-and-play-use-unit-testing-part-2-of-5/

Part 3: EF Record and play use: Make demo: http://msprogrammer.serviciipeweb.ro/2014/12/14/entity-framework-6-record-and-play-use-making-demos-part-3-of-5/ 

Part 4: EF Record and play use: Record user Sql when a bug occurs: http://msprogrammer.serviciipeweb.ro/2014/12/26/ef-record-and-play-use-recording-user-sql-when-a-bug-occurred-part-4-of-5/

Part 5: EF record and play: conclusions: http://msprogrammer.serviciipeweb.ro/2015/01/05/ef-record-and-play-conclusions/

 

Entity Framework Record And Play

With this helper you can record and then play the actions in Entity Framework(>= 6).

For recording actions just reference the dll and use

DbInterception.Add(new InterceptionRecordOrPlay(@"a.zip", ModeInterception.Record)); 

(Note: For ASP.NET you will use Server.MapPath("~/a folder that supports write/namefile.zip")

For replay use

DbInterception.Add(new InterceptionRecordOrPlay(@"a.zip", ModeInterception.Play));

This can be use for

  1. Unit Testing
  2. Making demos
  3. Recording user actions when a bug occurred

 

Source code is available at  https://github.com/ignatandrei/EFRecordAndPlay/wiki/

and has also a test 😉

There is also a NuGet package at https://www.nuget.org/packages/EFRecordAndPlay/ 

 

image

Javascript MVVM and ASP.NET MVC

TL;DR;

The purpose of this article is to show is how to transmit data to edit( create, update, delete) from a MVVM array to an ASP.NET MVC action in order for the action to bind to an IEnumerable/Array/List of objects. We will make also a javascript function that can be re-use across multiple MVVM frameworks to transmit data for multiple objects at once.

As always, you can find source code at https://github.com/ignatandrei/JavaScriptAndMVVMandMVC/ and you can view online at http://mvvmjavascriptmvc.apphb.com/

 

If you know already that, the last item on this rather long post is a homework. Download code and do it Winking smile

 

 

Prerequisites:

  1. If you want to know about ajax, please see the same example of how to save employee one by one http://msprogrammer.serviciipeweb.ro/2011/12/05/jquery-ajax-request-and-mvcdetailed/.
  2. The reference of sending an array of objects to MVC is http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/ . Please read it first since we will compose the Http request in ASP.NET MVC manner.
  3. If you do not know about MVVM and data binding in javascript, please follow most comprehensive tutorial that I know, http://learn.knockoutjs.com/

Objects

We start with the Employee ( Id, Name and IdDepartment) and Department(Id, Name). We will make an interface to display and edit multiple employees. The user can choose to change the Name and pick a Department from a list of Departments (presented as a select / dropdown / combox) .Also, he can create new Employee or delete an existing Employee. Then the user can submit all changes at once. We will use for this MVVM from Knockout, but you can use any other MVVM framework.

We will have 2 modes: edit and display. For edit, we have as actions add, delete ,modify and send all modifications(along with validation) . I would list what it is mandatory for every mode and action.

For fast learners:
Display
Edit Mode –Modify existing data
Edit Mode –add new employee
Edit Mode –delete existing employee
Edit Mode –send modifications and client validation
Summary
Homework


Display:

clip_image002

As you see we need to display the Employee list with name and the Department name.

If I do not want to create a NameDepartment property on Employee, but just use DepartmentId then the Model of the View should return the list of names of Departments.

public class ListEmployeesViewModel

{

public employeeList AllEmployees { get; set; }

public departmentList DepartmentList{ get; private set; }

This will be serialized as javascript array in the Home view:

@{

var jss = new JavaScriptSerializer();

var arrDepartments = jss.Serialize(Model.DepartmentList);

var arrEmployees = jss.Serialize(Model.AllEmployees);

}
//This is in the script tag in javascript:
//existing departments

var arrDeps = @Html.Raw(arrDepartments) ;

//existing employees

var arrEmps = @Html.Raw(arrEmployees) ;


So we have in arrDeps the departments and in arrEmps the existing employees.

To display the list of employees we create a MVVM javascript model( we have here knockout style, but is similar with other javascript MVVM framework)

First we create an employee in javascript ( explanations will follow) :

//this is in javascript
var emp = function(empId,name,deptId,active){

var self = this;

self.nr = i++; 

self.IdEmployee = ko.observable(empId);

self.NameEmployee = ko.observable(name);

self.Active = ko.observable(active);

self.iddepartament = ko.observable(deptId);

self.editMode = ko.observable(false);

self.displayMode= ko.observable(true);

self.deptName= function(){

var id=self.iddepartament();

var name ="";

$.each(arrDeps,function(index,value){

if(value.IdDepartment == id){

name=value.NameDepartment;

return false;

}

});

return name;

}

}

Explanation 1: the nr is the number of the employee . The user does not like ID, but wants to know how much employees are displayed.

Explanation 2: I have add an editMode and displayMode to the employee – to know the mode in which the employee is. I can have one property instead of 2(because of complementarity) , but was easier for me.

Explanation 3: In order to display DepartmentName it is enough to create a function on the employee to return the department name , iterating through the arrDeps – the code is

self.deptName= function(){

var id=self.iddepartament();

var name ="";

$.each(arrDeps,function(index,value){

if(value.IdDepartment == id){

name=value.NameDepartment;

return false;

}

});

return name;

}

Now we create the javascript model that holds all employees on the view:

var jsModel = function() {

var self = this;

self.employees = ko.observableArray([]);

And we make a function to add the existing employees to the array of employees:

self.addEmp = function(empId,name,deptId,active) { 

self.employees.push(new emp(empId,name,deptId,active)) 

};

And we add to the javascript MVVM model the existing employees

var model= new jsModel();

$.each(arrEmps,function(index,value){

model.addEmp(value.IdEmployee ,value.NameEmployee, value.iddepartament,value.Active);

});

And display it on the template by just binding :

ko.applyBindings(model);

that will repeat in

<tbody data-bind=’foreach: employees’>

<tr>

<td>

<span data-bind=’text: nr’ > </span>

</td>

<td>

<span data-bind=’text: NameEmployee,visible:displayMode’> </span>

<!—code removed for clarity–>

</td>

<td>

<span data-bind=’text: deptName(),visible:displayMode’> </span>

<!—code removed for clarity–>

</td>

<td>

<span data-bind=’text: Active,visible:displayMode’> </span>

<!—code removed for clarity–>

</td>

<td><!—code removed for clarity–>

</td>

</tr>

So this was the display mode. Pretty simple, huh ?

Edit Mode –Modify existing data

The Edit button calls the javascript model edit(true):

self.edit = function(val){

var arr =self.employees();

$.each(arr ,function(index,value){

value.editMode(val);

value.displayMode(!val);

});

So I put editMode to true and displayMode to false

Now, back to the template:

<td>

<span data-bind=’text: NameEmployee,visible:displayMode’> </span>

<input data-bind=’value: NameEmployee,visible:editMode’ />

</td>

You can see here visible attribute binded on displayModel and editMode –and how the span or the input are visible either way.

clip_image004

Same for the checkbox and the select. Because of the MVVM (in this case, knockout) any changes on the data ( name, active, changing department) will be binded back to the array of employees in the javascript MVVM model

Edit Mode –add new employee

When you press add a new employee is generated – the number 3:

clip_image006

It is easy – the Add button calls the same function addEmp that we use to push existing employees:

function BeginAdd(){

model.addEmp(0,'',0,true);

model.edit(true);

}

So a new employee is added to the array of employees – and the employees table is displaying the added employee . Do you like MVVM now ? 😉

Edit Mode –delete existing employee

The delete button have this code:

<td><button data-bind="click: $root.removeEmp,visible:editMode">Delete</button></td>

It is clear visible just when editMode is true. And the removeEmp removes the current employee from array, but having the id ( if not 0 – means new) put into a string that contains the ids of deletedEmployeesa:

 self.removeEmp = function(emp) { 

var id=emp.IdEmployee(); 

if(id != 0)

self.deletedItemsId += id;

self.employees.remove(emp); 

};

And the employees table is removing the row for the employee . Do you like MVVM now ? 😉

Edit Mode –send modifications and client validation

On the server side, the parameters of the action that receives the data is simple:

[HttpPost]

[HttpPost]

public JsonResult SaveEmployees(ListEmployeesViewModel e,string deletedItems)

I will explain the 2 arguments. For the first, remember ListEmployeesViewModel from the beginning ? It contains the list of employees and we will post that:

public class ListEmployeesViewModel

{

public employeeList AllEmployees { get; set; }

The second argument is the string that contains the id’s of deletedEmployees.

Now to transmit those from javascript array of employees.

Being a programmer, I like code-reuse. So why not create a function that iterates through an array( of employees), get all properties ( eliminating non-relevant, such as nr, editMode, displayModel and others) and compose the data in the MVC style(http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/ )

First, we need reflection in javascript:


//this is generic and can be put in a different .js file

var refProps= function (obj, exclude , recognizeFunction) {

var properties = [];

for (var prop in obj) {

//you can define an exclude function to exclude added properties

if(exclude){

if(exclude(prop))

continue;

}

var excludeProp = true;

var t = (typeof obj[prop]).toLowerCase();

if (t == 'number' || t == 'string' || t == 'boolean') {

excludeProp=false;

}

if(excludeProp){

//special case :maybe it is a observable function 

if(recognizeFunction){

if(t == 'function' ){

if(recognizeFunction(t))

excludeProp=false;

}

};

}

if(!excludeProp)

properties.push(prop);

};

return properties;

}

Fast explanation of parameters:

  1. obj is the object in javascript that I need all properties that are number, string, or boolean.
  2. I need to remove some properties(nr,editMode, displayMode) that are relevant in javascript – but not on the server side – so I have put an exclude function( you can put null)
    function exclude(prop){
    
    switch(prop){
    
    case "nr":
    
    return true;
    
    case "deptName":
    
    return true;
    
    case "editMode":
    
    return true;
    
    case "displayMode":
    
    return true;
    
    default:
    
    return false;
    
    }
    
    
  3. Also, knockout make a special ko.observable function
    self.NameEmployee = ko.observable(name);
    

    – so I need to recognize those functions – and the function is(surprise!) ko.observable

Now saving the array is again re-usable:

function saveArray(itemsArray,/*you can not pass those*/prefix, excludeProp,recognizeFunction,validateProp){

var l = itemsArray.length ;

if(l == 0){

return "";

}

var propNames = refProps(itemsArray[0],excludeProp,recognizeFunction); // you can pass null on exclude to add all properties

var nr = 0 ;

var strData="";

for (var i = 0; i < l; i++) {

var objToSave= itemsArray[i]; 

//you can pass here another function to recognize which object can be saved

//if(!canBeSaved(objSave) continue;

for (var j = 0; j < propNames.length; j++) {

var nameProp = propNames[j];

var val =objToSave[nameProp] ;

var t = (typeof val).toLowerCase();

if(t == 'function'){

val = objToSave[nameProp]();

}

if (validateProp) {

if (!validateProp(nameProp,val, objToSave, i)) {

return "";

}

}

strData += "&"+ prefix+"[" + nr + "]." + nameProp;

strData += "=" + val;

}

nr++;

}

return strData;

}


The itemsArray parameter is the items array that you want to save ( in my case, the employees).

The new function is validateProp – you can pass null – but this is an implementation that take into consideration that the employee should not have the name empty and the user must select something from the department list:


function validateProperty(propName, value, item, number){

switch(propName){

case "NameEmployee":

if(value == ""){

window.alert("please enter employee name for row number " + (number+1) );

return false;

}

return true;

case "iddepartament":

if(value === undefined || value == 0){

window.alert("please select a department for row number " + (number+1) );

return false;

}

return true;

default:

return true;

}

}



After those 2 re-usable functions( saveArray and refProps ) the code for save is pretty simple:

We obtain the values for employees using saveArray

self.save = function() { 

var itemsArray = self.employees();

var strData = saveArray(itemsArray,"AllEmployees",exclude, ko.observable,validateProperty);

if(strData == "")

{

//window.alert("no save");

return;

}

strData="deletedItems=" +self.deletedItemsId + strData;

window.alert("saving:" + strData);

and post to the server.


$.ajax({

type:"POST",

url:'@Url.Content("~/Home/SaveEmployees")' ,

data: strData ,

datatype:"JSON",

//Just we must be attentive: if success , then the id of the new employees( those with id’s 0) must be replaced by the id’s of the id’s generated on server.
//How I identify if multiple new employees? Well, it is easier to delete all employees with id’s 0 and add the id’s that are not already in the array:

var dels=[];

//delete the new items and add the new ones

var idExisting=';';

$.each(self.employees(), function(index,emp) {

if(emp.IdEmployee() == 0 )

dels.push(emp);

else

idExisting += emp.IdEmployee()+";";

});

$.each(dels,function(index,emp) {

self.removeEmp(emp);

});

//add new one

window.alert('add new ones');

$.each(returndata.emps,function(index,emp) {

var id=emp.IdEmployee;

if(idExisting.indexOf(";" + id+";") == -1){// not found - means it is a new one

self.addEmp(emp.IdEmployee ,emp.NameEmployee, emp.iddepartament,emp.Active);

}

});


Also, for Antiforgery token I have used this code

 //added antiforgery token
                var aft= $('input[name="__RequestVerificationToken"]');
                if(aft.length){
                    strData +="&__RequestVerificationToken=" + aft.val();
                }

Well, that was it !

Summary:


We have had an javascript array of employees to edit and send data at once . We have make the POST as for ASP.NET MVC rules. You can re-use the refProps javascript function( that gives you the name of the properties of an object – in our case, employee) and saveArray javascript function – that serialize an javascript array to a recognizable ASP.NET MVC idiom

As always, you can find source code at https://github.com/ignatandrei/JavaScriptAndMVVMandMVC/ and you can view online at http://mvvmjavascriptmvc.apphb.com/

 

Homework for you:

( fork on github  and send me the solution via github)


1. Modify the nr ( the employee order number) such as , when deleting or adding a new employee, the numbers are in good order – not 1 and 3 like in the picture

clip_image008

2. Add a hiredate to the employee . Ensure you transmit the date(Hint: Modify the refProps )

LaterEdit:
Hintea Dan Alexandru made a simple application to show me that a simple json.stringify it is enough for MVC to do this magic.
More , it shows directly in the MVVM model a toDTO that is simplier to use( however, the validation part remains to do)
Source code at https://github.com/hinteadan/MvcAjaxSample/#!

MVC Export List of objects to Excel-Word-PDF-CSV-HTML-XML–Razor style

This is the second part of the demo of the Exporter  in action  – this time in MVC .

It is a little more complicated, because you need to show to the exporter the full path where to put the generated file

string filePathExport = Server.MapPath(“~/exports/a” + ExportBase.GetFileExtension((ExportToFormat)id));

All others are the same easy stuff  -add Nuget package and export in 3 lines – and all action code is 6 lines long:

            List<Electronics> list = Electronics.GetData();
            ExportList<Electronics> exp = new ExportList<Electronics>();
            exp.PathTemplateFolder = Server.MapPath("~/ExportTemplates/electronics");
            string filePathExport = Server.MapPath("~/exports/a" + ExportBase.GetFileExtension((ExportToFormat)id));
            exp.ExportTo(list, (ExportToFormat)id, filePathExport);
            return this.File(filePathExport, "application/octet-stream", System.IO.Path.GetFileName(filePathExport));

 

 

 

 

GitHub Demo at https://github.com/ignatandrei/Export_Word_Excel_PDF_CSV_HTML

The Nuget package is at http://www.nuget.org/packages/Exporter/

YouTube demo at http://youtu.be/DHNRV9hzG_Y