Sunday, November 6, 2016

MVC 5: Custom DataAnnotation with Client Side Validation

  [Required]  
     [MinValue(50, "Number", "minimum value is 50")]  
     public int Number { get; set; }  

Custom ValidationAttribute Code:

 public class MinValueAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute, System.Web.Mvc.IClientValidatable  
   {  
     private String PropertyName { get; set; }  
     private readonly int _minValue;  
     public MinValueAttribute(int minValue, String propertyName, String errormessage)  
     {  
       this._minValue = minValue;  
       this.PropertyName = propertyName;  
       this.ErrorMessage = errormessage;  
     }  
     public override bool IsValid(object value)  
     {  
       return (int)value >= _minValue;  
     }  
 }  

Override the method GetClientValidationRules to add data-val attributes to html5 code.

 public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context)  
     {  
       var modelClientValidationRule = new ModelClientValidationRule  
       {  
         ValidationType = "minvalue",  
         ErrorMessage = this.ErrorMessage,   
       };  
       modelClientValidationRule.ValidationParameters.Add("minval", this._minValue);  
       yield return modelClientValidationRule;  
     }  
Client Side code: add this code in files called minvalValidation.js
 $.validator.addMethod("minvalue", function (value, element, params) {  
   var minLength = $(element).attr("data-val-minvalue-minval");  
   if (value < minLength) {  
     var message = $(element).attr('data-val-minvalue');  
     $.validator.messages.minvalue = message;  
     return false;  
   }  
   return true;  
 });  
 $.validator.unobtrusive.adapters.add('minvalue', function (options) {  
   options.rules['minvalue'] = options.params;  
   if (options.message != null) {  
     $.validator.messages.minvalue = options.message;  
   }  
 });  

Wednesday, September 30, 2015

Copy GAC Files from One Server

In order to copy GAC files (Assembly .dll files) from one server to another follow the following steps:

1. on the CMD run the command:

    regsvr32 /u C:\windows\Microsoft.Net\Framework\v2.0.50727/shfusion.dll

This command will Create the GAC files into Folders where you can view the dll file.

2. Open the folder C:\Windows\assembly\GAC_MSIL. this folder contains all the assembly files as folders with dll file inside it.

3. Copy the Folder you need into the remote server (New Server you want to transfer the assembly to).

4. Copy the dll file to C:\ drive; for example: Microsoft.Web.Media.SessionHelper.dll

4. Open the Visual Studio CMD and write down the following command:

     gacutil /i C:\Microsoft.Web.Media.SessionHelper.dll and press enter.

If you got the message: Assembly successfully added to the cache, then you have successfully transferred the gac file from one server to another.

Tuesday, September 29, 2015

Oracle Client 12 64bits error: Installation failed to access the temporary location

If you encounter this error while installing Oracle client 12 64bits on windows 7 or windows server 2008, 2012 then do the following:

1. Go to Network and sharing Center -> Advanced sharing settings -> Turn On File and Printer Sharing and Turn on sharing so anyone with network access can read and write files in the public folders
2. Ensure that C$ share is enabled, and Administrator has full privileges on it (This can be checked by Advanced Sharing option when share the C:\ drive.
3. Make sure that the cmd command net use \\computer name\c$ works successfully. please make sure this command works and be aware to the computer name not localhost or IP address. If the command didn't work then go to hosts file and add the computer name with 127.0.0.1 record to the hosts file.
4. I don't if this step is required but do it in case all the above steps failed: go to regedit and browse to: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
and add new DWORD value called (LocalAccountTokenFilterPolicy) with value = 1.
5. You could change the temp and tmp locations in the local Environment variables tab to other locations than C:\users\admin\app data.........
6. Don't stop the services Server and Workstation. Keep them running so that sharing operations work successfully.
7. If you find a service related to Oracle then stop it.

Wednesday, May 13, 2015

Solving Rotativa Unhandled Exception Error

Rotativa is a great tool used to convert your html views to PDF files in web projects, it works fine with ASP.Net webforms and MVC where razor views can be converted to readable pdf, more information about Rotativa in the link below:

Rotativa Official website

You can Also download Rotativa for ASP.Net Nuget package in this link.
Rotativa Nuget

While working on different servers I have an error with unhandled exception when using rotativa, the error was:

Exception Description:: System.Exception at Rotativa.WkhtmltopdfDriver.Convert(String wkhtmltopdfPath, String switches, String html) at Rotativa.WkhtmltopdfDriver.Convert(String wkhtmltopdfPath, String switches) at Rotativa.AsPdfResultBase.CallTheDriver(ControllerContext context) at Rotativa.AsPdfResultBase.BuildPdf(ControllerContext context) at Rotativa.AsPdfResultBase.ExecuteResult(ControllerContext context) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass1e.<>c__DisplayClass28.b__19() at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass1e.b__1b(IAsyncResult asyncResult)

After investigating with the issue, I start thinking of running the Rotativa execution program from the Command Prompt, like this:

wkhtmltopdf.exe README.txt test.pdf

So I Got an error:



This error is a missing C++ redistributable Package for Visual studio 2013 file called (MSVCP120.dll).

To solve the issue:
1. Open the C++ redistributable Package for Visual studio 2013 downloadable link below:
download Visual C++ Redistributable Packages for Visual Studio 2013

2. Click Download and choose the file (vcredist_x86.exe) even if you are running X64 bit server version.

3. Install the file.

this will add the missing dll file mentioned above, and the problem is now solved.

Happy Codding.

Thursday, January 22, 2015

Custom Http Module runs only with Integrated Pipeline mode on IIS application pool

When you write custom HTTP module in your .Net Application to run custom code at the application start event, you have to set the Application pipeline to Integrated Mode so that the application can see your custom HTTP module in the IIS and run it.
The problem rises when you publish MVC web application on the IIS with pipeline mode Classic, then you will see the error:

Error: An ASP.NET setting has been detected that does not apply in Integrated managed pipeline mode.


To solve this problem, and keep your custom Http Module working correctly, then you may edit the web.config file with the following attribute.


       
   
 <configuration>  
   <system.webServer>  
     <validation validateIntegratedModeConfiguration="false"/>  
   </system.webServer>  
 </configuration>  

Tuesday, May 6, 2014

Adding View or Table when no key or primary key is Inferred to edmx model EF5

Sometimes when you work on entity model (edmx) and want to add a view or table that doesn't have a primary key or non-nullable field (this case specially arise when you add a view to the model), then you end up with warning message says:

"Error 6013: The table/view  does not have a primary key defined and no valid primary key could be inferred"

I have googled it, and the answer was to modify the edmx xml file () to add this view manually to the edmx.
The steps are straightforward, but need to copy paste the solution when ever you want to update the model which will override your modified code. So rule #1 in this post is:

"When you do some manual modifications to the edmx file, you must take a copy of the text before updating the model".

ok, let say that you have a view which shows the number of students in each faculty in the university named INV (Institute of Nano Velocity).
the View name is: V_INV_TOTAL_STU, which has columns:

FAC_CODE: number.
FAC_NAME: Varchar2 (max: 4000 bytes).
TOTAL: number.

Now the following will show how to work manually with EF5 and edmx model file.

Step1:
Try to add the view from the update model option in the edmx file automatically, or at least try to.
If the above error (6013) appeared then right click the edmx file and choose edit with XML Editor

When the edmx opened in xml do the following:

1. Uncomment the entitytype generated automatically in the



Note: nullable="false" must be added to the property so that FAC_CODE will be the key of the view.

2. Add the following code in the


3. in the at the tag add the following:


4. Add the following Code in the  :
 Note: this will map the column name to the corresponding property in the model.
         

Save the edmx file.

Step2:
Now its time to map or bind this view to its corresponding model, so create a new class in the models folder named V_INV_TOTAL.cs.
then add the following properties to it:
        public int FAC_CODE { get; set; }
        public string FAC_NAME { get; set; }
        public Int64 TOTAL_REQUESTS { get; set; }

Step3:
The last step is to modify the model.context.cs file which will connect to the DB.
add this code to its properties:

public DbSet V_INV_TOTAL_REQUESTS { get; set; }.

Now you are ready to work on with this new model in your controllers and views.
Again I want to remind you to take a copy of the modified edmx and context files generated automatically when you create the edmx model for the first time, because once you want to update the model, then these files will be overwritten.... so be careful.



references:


Also i have found this tool from VisualStudio 2013 team, hope it will much easier than the steps provided in this post:



Wednesday, April 30, 2014

Use Scalar Function with Entity Framework and MVC 5 project

I have faced the challenge of using scalar function within select statement in SQL or Oracle in mvc project for example: 

select hr.get_emp_name(:P_EmpID) from dual 

So suppose you have an edmx model with the views selected and you want to add the statement above and use it, the problem with this scalar function is the way its being used, its look like a normal select statement, not like stored procedures where it expects input parameter and output parameters.

Well after searching the Internet for the answer and after reading many blogs and articles with some help with my friends I have reached to the right and easy way to do so.

Step1:
Open the model1.edmx diagram and write click on it and choose (Update Model from Database).
When the dialog open go to the (add) tab and expand the stored procedures and functions extension.
Select your schema and then select the scalar function you want to represent in your model, let say the function name is hr.get_emp_name(P_EmpID as string) from the dbo schema.
Note: Make sure to remove the check box (Import Selected Stored procedures and functions into entity model). because you will get a warning that this function can't be imported and it is not added to the model.

Step 2:
After that if you go to the Model Browser Window and expand the model1.edmx, then expand Model.Store, then expand Stored Procedures or Functions, you will see function you have added in step one with the name hr_emp_name and under it you will see it has a parameter named P_EmpID.
until now everything is cool, now lets move to the most important step; step3.

Step3:
In this step you will modify the model.edmx file xml file, yes you will do some dirty nifty things in the XML.

Ok then, wake up, you are a programmer !!!

Ok, now right click the model1.edmx file from the Solution Explorer and click open with,
use XML Editor and open the file; it may ask you to close the diagram file if its opened, click ok.

Press ctrl+f to search for the word (function), and you will find the function you added in step one as xml tags starts with

ok now, you have to modify these parameters in the function tag:
IsComposable="false"
Remove the ReturnType attribute.
Remove StoreFunctionName attribute, becuase its a function not a stored procedure.
Add attribute: store:Name="hr.EMP_NAME", means i want to execute this function.

Then after the function opening tag add the CommandText tag:

            select dbo.HR.EMP_NAME(:P_EmpID) from dual


Make sure you have a parameter named P_EmpID.

as a result your function tag must look like the one below:

HR_EMP_NAME
" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="DBO" store:Name="hr.EMP_NAME">         
            select dbo.HR.EMP_NAME(:P_EmpID) from dual
         
          P_EmpID" Type="varchar2" Mode="In" />


As a result you will save the xml file, build the project and close the xml file.
Now we will move to step4

Step4:
In this step you will import the function you have add to the entity model, this step didn't complete if you check the import stored procedures and functions to entity model in step1.

So, go again to the model1.edmx diagram and browse the Model Browser, expand the Model.Store, then expand Stored Procedures or Functions, and double click the function you have added with the name hr_emp_name.

The Import function will open now,
write down the function name you want.
Uncheck the Function Import is Composable.
Then chose the function from the dropdown list which is HR_EMP_NAME.
Return the collection depends on your function, in our case the function will return scalars of type string, sometimes you may return none or an entity.
Ok for now, click generate column info, and you may get an exception i didn't solve till this post. then click ok and save.

Step5:
Now its time to use the function inside a controller.
If you open the model1.context.cs file after save and build everything you will notice the definition of the function with something like this below:

public virtual ObjectResult<string> HR_EMP_NAME(string P_EmpID)
        {
            var P_EmpIDParameter = P_EmpID!= null ?
                new ObjectParameter("P_EmpID"P_EmpID) :
                new ObjectParameter("P_EmpID", typeof(string));
    
            return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("HR_EMP_NAME", P_EmpIDParameter);

        }

To use it in the a controller

string empName = "";
            empName = _db.HRINFO_EMP_EMAIL("55214").First();
            if (!string.IsNullOrEmpty(empName))

                ViewBag.empName empName ;

Cool ha, i know its somehow complex but I hope this was useful for you.