Jan 31, 2018

ASP.NET MVC custom culture client validation

Further info here: http://www.c-sharpcorner.com/article/internationalization-in-asp-net-core-mvc/

Watch for @inject ... for Localization property

Install NuGet packages:
- jquery-globalize.0.1.3
- jquery.validation
- Microsoft.jQuery.Unobtrusive.Validation

Choose your culture and properly initialize globalize library:

    <script src="~/Scripts/globalize.0.1.3/globalize.js"></script>

    <script src="~/Scripts/globalize.0.1.3/cultures/globalize.culture.hr.js"></script>
    <script>

        $(document).ready(function () {

            Globalize.culture("hr");

            $.validator.methods.number = function (value, element) {

                return this.optional(element) || !isNaN(Globalize.parseFloat(value));

            }

            $.validator.methods.range = function (value, element, param) {

                return this.optional(element) || (Globalize.parseFloat(value) >= param[0] && Globalize.parseFloat(value) <= param[1]);

            }

            $.validator.methods.date = function (value, element) {

                return this.optional(element) || Globalize.parseDate(value);

            };

        });

    </script>

This handles check on client side on input values.

I haven't tried but for input validation there is DataFormatString param validation:


[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime? BirthDate { get; set; }

https://stackoverflow.com/questions/13916991/mvc-datatype-errormessage

Dec 1, 2017

.NET Core 2.0 Tips For Beginners

Update 24.9.18

Since key feature of .NET Core is sandbox (running concurent Core app's with different versions of .NET Core) one needs to understand basics of .NET Core versioning. Here is good post on subject:

Issue - project has invalid or missing dependencies but SDK or NuGet package(s) exist

From DevCommand prompt navigate to Project folder (not root !) where is your PRJ file and run:

dotnet restore

ASP.NET Core 2.0 configuration


To make above example work add NuGet package:

Microsoft.AspNetCore.All
Microsoft.NETCore.App  <-- it seems that this one is by default, can't be removed?

Make sure to mark appsettings.json with Copy If Newer


Setting up IIS hosting of ASP.NET Core on development PC

https://docs.microsoft.com/en-us/aspnet/core/publishing/iis?tabs=aspnetcore2x

Tip. No need for any extra coding. Just make sure to setup IIS. I think ASP.NET CoreModule is required.

WebAPI


  • There is not API route configuration in startup. Use this for each controller:


    [Route("api/[controller]/[action]")]

; then each action decorate like this:

        [HttpGet("{echoText}",Name ="Ping")]
        public PCPingRS Ping(string echoText)



  • If you need to execute something at app startup, what you have previously done in Global.asax Startup, now is not that simple.
    • You need to take into account Dependency Injection since all Core is supporting it by default.
    • You may try to place your calls inside:
               return WebHost.CreateDefaultBuilder(args)             

.ConfigureAppConfiguration((context, config) =>
{
config.SetBasePath(Directory.GetCurrentDirectory());

  • Parameter binding - you CAN NOT bind more than one simple value type parameter from POST body using [FromBody]
    • This works:
      public ActionResult DoSomething( [FromBody] string myText )
    • But this doesn't:
      public ActionResult DoSomething( [FromBody] string myText, [FromBody] int year)
  • Parameter binding - POST - you MUST always use [FromBody] since WebAPI is capable to map complex type memebers from Uri
    • public ActionResult DoSomething( [FromBody] MyObject dummy )

Session

For some reason this:

_httpContextAccessor.HttpContext.Session.SetObject(_searchObjectContextKey, searchObjectModel);

works and saves to Session but this:

_httpContextAccessor.HttpContext.Session.SetObject<SearchObjectsModel>(_searchObjectContextKey, searchObjectModel);

; doesn't and it has no error.


Use inject to reference namespaces:

@inject MyNameSpace.MySubSpace


Good resources on new tags helpers in Core :

https://docs.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro


Partial views  vs ViewComponent

https://forums.asp.net/t/2083792.aspx?What+is+the+advantage+of+View+Components+in+ASP+NET+Core+1+0

Ideally you should not design components / controls inside partial views.
Partial views should encompass only reusable layout with minimum presentation logic.
If there is complex js or servers side logic you should use view component since it provides clear separation of controller.

Sections

Often there is some JS code required by partial view. You may use @section Scripts in your layout to place together all you scripts created outside from layout.
Unfortunately you CAN'T use section tag in PARTAIL views!
Hence you can't easy place your JS code with your partial view. Why is that?
Above section explains it. You are not suppose to place any logic even client side in your partial view.
You may place your section tag only in Views. This design degrades your partials to mere HTML containers. All your JS code from all partials should be placed in hosting view.
In real world this is not so bad. You want to reuse partial's and their JS code. Right?
So place your JS in standalone JS file and then reference it and initialize from hosting view.
This makes sense. Ideally you should write one-liner in JS to reference proper initialization for your partial views.

Debuging


Open VS command prompt. Go to folder where is your solution.
DOTNET RUN
Attach debuger to DOTNET process.

Logging


Core has integrated logging. Turn it on like this:
<aspNetCore processPath="dotnet" arguments=".\App.dll" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" />

Don't forget to create logs folder.

Initial setup on IIS - How to prepare self-contained installation 


https://docs.microsoft.com/en-us/dotnet/core/deploying/deploy-with-vs

Key points:
1. Manually edit your CSPROJ file and modify like this:
<PropertyGroup>
    <OutputType>Exe</OutputType>
    <RuntimeIdentifiers>win10-x64</RuntimeIdentifiers> 
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>
2. Perform Publish to folder
3. In publish folder edit web.config and enable Logging as noted above
4. Copy content to IIS folder with no managed code app pool
5. Create logs folder in root of your website



Oct 18, 2017

Javascript Ajax requests concurency, single thread, behavior - REPOST

https://stackoverflow.com/questions/7238586/do-i-need-to-be-concerned-with-race-conditions-with-asynchronous-javascript/7238663#7238663
https://stackoverflow.com/questions/7868434/are-calls-to-javascript-methods-thread-safe-or-synchronized/7868445#7868445
https://stackoverflow.com/questions/7575589/how-does-javascript-handle-ajax-responses-in-the-background/7575649#7575649

Aug 30, 2017

XSLT - basics, tips & tricks

This post is created from Pluralsight video:
XSLT 2.0 and 1.0 Foundations by Dimitre Novatchev

You can "develop" XSLT in Visual Studio. Create or open XSLT as simple file and execute Start debugging from Debug menu.

You can't learn XSLT without XPath.

XSLT is built around concept of templates.

XSLT can use one or even more XML as input data. Templates can be viewed as peace of code that must target using XPath some elements of XML input.

Ideally you are responsible to write templates that should cover all input data. You can do this with 1 or unlimited number of templates. Each template may nest another. This relates to inherited hierarchy of XML.

Furthermore you should be aware that there is priority and precedence applied on templates. It determines order of execution and resolve conflicts if two templates match same data.

Sample:

<xsl:template match="persons">

<!-- Render any data related to all persons -->

   <!-- Here nesting happens. XSLT processor will search for templates in rest of XSLT document that match XML data from this contextual point/node -->

    <xsl:apply-templates/>

</xsl:template>

Following template matches person and renders it inside above <xsl:apply-templates/>

<xsl:template match="person">

<xsl:value-of select="first-name"/>

<xsl:value-of select="last-name"/>

</xsl:template>


Built-in templates

By default XSLT processor will catch and render all data from source XML that hasn't been processed by your templates. Of course this is rarely wanted behavior.

Dimitre Novatchev has written templates that override these built-in template and outputs descriptive warning about missing matches for elements, nodes, attributes which is very helpful.

<!-- Built-in templates: Explicit  -->
  <xsl:template match="*" mode="#all" priority="-999">
    <xsl:message>
      Unmatched element <xsl:value-of select="name()"/>
    </xsl:message>
    <xsl:apply-templates mode="#current"/>
  </xsl:template>

  <xsl:template match="text()" mode="#all">
    <xsl:message>Unmatched text node</xsl:message>
    "<xsl:value-of select="string(.)"/>"
  </xsl:template>

  <xsl:template match="@*" mode="#all">
    <xsl:message>
      Unmatched attribute <xsl:value-of select="name()"/>
    </xsl:message>
    <xsl:value-of select="string(.)"/>
  </xsl:template>

Overriding templates

If you explicitly don't want to render some data just write empty template:

<xsl:template match="person" />


Pull vs Push stlye

This:

<xsl:apply-templates />

; is push style. We didn't target which explicit templates we want here so they'l get pushed in document order.
When following template gets executed:

 <xsl:template match="name|age|profession">
   <td><xsl:value-of select="."/></td>
 </xsl:template>

; we can't force order in which name, age or profession are rendered. Order is determined by input XML data. To change this use pull style.

For XSLT 1.0 use:

     <xsl:apply-templates select="name"/>
     <xsl:apply-templates select="age"/>
     <xsl:apply-templates select="profession"/>

This way we explicitly match place to render with code that renders it with select attribute.

Variables

They follow naming and expression that you should know from XPath.

<xsl:variable name="personsCount" select="count(person)"/>

<xsl:value-of select="$personsCount"/>

When defined as child of top <xsl:stylesheet> element it is global.
Here is an example of local:

<xsl:variable name="fullName" select="concat(name,' ',age)"/>
<xsl:value-of select="$fullName"/>

Modularity

As in procedural languages you can place your XSLT code in separate files or modules.
You reference these modules using :
- <xsl:include>
- <xsl:import>

Code included with Include has higher importance. It is treated as if it was written in primary stylesheet. If by mistake you INCLUDE same code you'll create conflict. Include instruction may be placed anywhere.
Import on the other hand can't create conflict in primar stylesheet. It's content is always treated with less precedence and priority than one in primary stylesheet. You must write it as the very first child of <xsl:stylesheet>
Precedence is determined by order of IMPORT instructions. Last one wins.

Precedence

When 2 or more templates match same XML content XSLT processor must choose a winner.
This is usually case for complex xslt comprised from multiple import/includes.
In such cases same match in different xslt modules may occur.
One solution is to play with priority attribute of template instruction:

<xsl:template match="name|age|profession">
   <td><xsl:value-of select="."/></td>
 </xsl:template>

  <xsl:template match="name|age|profession">
    <td style="color:red">
      <xsl:value-of select="."/>
    </td>
  </xsl:template>

Observe in above sample that both templates match same data. There will be no error and LAST template in document order will be the winner.
Alternatively we could change first template like this:

<xsl:template match="name|age|profession" priority="2">

This way the first template would win.

Same rule goes for variables. Variable from imported module has LESS priority then same one in primary stylesheet.

Data types

<xsl:variable name="salary" select="xs:decimal(0.1)"/>

For-each

Loop is very similar to apply templates.
There is support for sorting:

      <xsl:for-each select="person">
         <xsl:sort data-type ="text" select="age" order="descending"/>
         <p>
             <xsl:value-of select="name"/>
           <xsl:value-of select="age"/>
           <xsl:value-of select="profession"/>
         </p>          
       </xsl:for-each>

Sorting

You can perform sorting on both for-each and apply-templates instructions on same way:

       <xsl:apply-templates>
           <xsl:sort data-type ="text" select="age" order="descending"/>
         </xsl:apply-templates>

Apply-templates vs for-each

Dimitre Novatchev made great example for this:

XML document:

<creatures>
  <animal species="dog"/>
  <animal species="cat"/>
</creatures>

XSLT document:

<xsl:template match="creatures">
   <xsl:apply-templates mode="say"/>
 </xsl:template>

 <xsl:template match="animal[@species='dog']" mode="say">
   Dog says: "Bow" ...
 </xsl:template>
 <xsl:template match="animal[@species='cat']" mode="say">
   Cat says: "Meauu" ...
 </xsl:template>
<xsl:template match="text()" mode="say"/>


Foreach is functionally equivalent foreach in C#. Apply template can be viewed as virtual method.
In above example first template resembles abstract class. It creates generic behavior for functionality Say of animals. Than more specialized templates handle specific cases for each animal. We could say it resembles overriding virtual methods.
Observe last template. If all fails it gets executed. Do note use of mode attribute.

Bottom line is to use for-each for simple tasks and apply-templates for complex problems that are easier solved using more than one place for code.

Aug 29, 2017

XPath - Examples

// equals descendant-or-self::node()/

Watch it! // is expensive since it is relative path and has to traverse all tree!

Case sensitive names of nodes, elements and attributes !

//Person   is not equal   //person

Everything inside [ ] is expression. When you need another expression inside [ ] sometimes you can write:

//person[address/city]
; in this case / is used inside [] instead of :
//person[address[city]]

Relative and absolute path

Example of relative path:

//person[1]  

; this will return EVERY person that is the FIRST child of its parent ! In sample this will include "Oliver child person" and John Sullivan.

Another relative:

//*/*/*/*/name()

; every element that has 4 ancestors ( city -> address -> person -> persons -> root

String='city'
String='person'
String='city'

Absolute path:

/persons/person[1]

; or use :

(//person)[1]

; this will return only FIRST child of persons node!

Sample XML:

<?xml-stylesheet type="text/xml" href="persons.xsl"?>
<persons>
  <person>
    <id>1</id>
    <age>20</age>
    <first-name>
      John
    </first-name>
    <last-name>
      Sullivan
    </last-name>
    <salary>200.00</salary>
  </person>
  <person>
    <id>2</id>
    <age>25</age>
    <first-name>
      Mark
    </first-name>
    <last-name>
      Johny
    </last-name>
  </person>
  <person>
    <address>
      <city state="France">Paris</city>
    </address>
    <id>3</id>
    <age>30</age>
    <first-name>
      Mark
    </first-name>
    <last-name>
      Johny
    </last-name>
  </person>
  <person>
    <address>
      <person>
        Oliver child person
      </person>
      <city state="UK">London</city>
    </address>
    <id>4</id>
    <age>40</age>
    <first-name>
      Oliver
    </first-name>
    <last-name>
      Johny
    </last-name>
    <salary>300.00</salary>
  </person>
  <person>
    <id>5</id>
    <age>60</age>
    <first-name>
      Kris
    </first-name>
    <last-name>
      Sullivan
    </last-name>
    <salary>300.00</salary>
  </person>
</persons>

1. Get all persons:

//person

2. Get all persons text:

//person/string()

3. Get second person:

//person[2]

;returns: Mark, Johny, Id=2

4. Get fourth person:

//person[position() eq 4]

;returns: Oliver, Johny, Id=4

5. Get first two persons:

//person[position() lt 3]

6. Get persons that have element Salary:

//person[salary]

7. Get every person whose next person sibling in document order has salary that equals to preceding person.

//person[sallary = following-sibling::person/sallary]

8. Get persons whose age is between 20 and 60 and has position before filtering greater than 3 :

//person[age gt "20" and age lt "60" and position() gt 3]

9. Find persons whose salary is greater than salary of first person that has info about salary:

//person[salary gt //person[salary][1]/salary/text() ]

10. Look for persons that have City info. For them look their parent Person and person Id.

//person/address/city/../../id

11. Find cities whose attribute State is France:

//person/address/city[@state="France"]

Example of sequences introduced in XPath 2.0:

12. Iterate through all persons and output first-name value:

for $n in /persons/person return $n/first-name

13. Iterate all persons with value for salary. On each iteration calculate second sequence by multiplying current person id element value from from first sequence with 2.

for $n in /persons/person[salary], $id in $n/id * 2 return $id

14. Are there any person that has salary greater than $299.00 :

every $p in /persons/person/salary satisfies $p gt "299.00"

;returns true

15. Do all persons older than 18 have salary element ?

every $adult in /persons/person[age gt "30"] satisfies $adult[salary]

;returns true

16. Do at least one person that have city info have salary info:

some $personwcity in /persons/person/address/city satisfies $personwcity/../..[salary]

;returns true

17. Show last Person from Persons node:

/persons/person[last()]

18. Show first-name of persons whose Id is greater than 3. Observe use of dot  as self reference.

/persons/person/id[. gt "3"]/../first-name

19. Show first and last person.

(//person)[1] union (//person)[last()]

20. Show only persons with city info and salary info

Version 1:
//person[address/city] intersect //person[salary]

Version 2:
//person[address/city and salary]

21. Show persons that DON'T have salary:

//person except //person[salary]

22. Show all persons ONLY if there are 2 or more persons with address info:

//person[count(/persons/person/address) ge 2]

Aug 21, 2017

T-SQL - sample data script - creating random data

If you want more data just add to cross joins more sys tables.
Be careful since row count grows exponentially. 

CREATE TABLE Department (
DepartmentID int primary key not null identity,
[Name] nvarchar(4000)
)
CREATE TABLE Employee (
EmployeeID int primary key not null identity,
DepartmentID int,
constraint fk_employee_department foreign key (departmentid) references department(departmentid),
[Name] nvarchar(4000)
)
--Creating roughly 100000 dummy rows
INSERT INTO Department (Name)
SELECT
sys.objects.[Name]
FROM
sys.objects, sys.indexes, sys.tables
--Creating roughly 600000 dummy rows
INSERT INTO Employee (
DepartmentID, [Name]
)
SELECT
ASCII(LEFT(newid(),1)) AS DepartmentID,
sys.columns.[Name]
FROM
sys.objects, sys.columns, sys.tables