Showing posts with label Exceptions. Show all posts
Showing posts with label Exceptions. Show all posts

Monday, April 27, 2015

How to Fix the OptimisticConcurrencyException in MVC

In this post we describe Step by step How to Fix the OptimisticConcurrencyException in MVC.  
We take care here in just 5 minutes of the errors raised by the Entity Framework while the EDM (Entity Data Model) is confronting a database concurrency issue.

In short, when two or more users try to modify data simultaneously , SQL offers two types of Concurrency Control:
1) Pessimistic Concurrency : lock the data table in advance because someone for sure will try to   affect your changes simultaneously. Action to perform: LOCK the table!
2) Optimistic Concurrency : make your changes and let's hope none will try to alter the record in the meantime. Action to perform: raise an error if the record was altered in the meantime!

Our approach here will be: if indeed the record was altered from the original (AKA the "OptimisticConcurrencyException" was thrown), then we'll refresh the data and save your important updates with a "Client Wins" policy.


How to Fix the OptimisticConcurrencyException in MVC


To apply our approach, we'll use here a "Save(object itemToSave, int #noOfItemsToSave )" method, wrapping the context's SaveChanges().
We just add here a "catch" block to the C# method which tries to update an item to the database.
This way we enforce refreshing the item and saving all your changes overriding the refreshed data.
Therefore, add the following method to your Data Repository (copy-paste:) :

public bool Save(object target, int RecordsNumber)
        {
            try
            {
                return Context.SaveChanges() == RecordsNumber;
            }
            catch (OptimisticConcurrencyException)
            {
                ObjectContext ctx = ((IObjectContextAdapter)Context).ObjectContext;
                ctx.Refresh(RefreshMode.ClientWins, target);
                return Context.SaveChanges() == RecordsNumber;
            }
        }


As you see, the return value tells that all edited items have been successfully persisted to database.
Then you can use this method from your MVC Controller as follows:


 [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(Blog blog)
        {
            if (ModelState.IsValid)
            {
                db.Update<Blog>(blog);
                db.Save(blog, 1);
                return RedirectToAction("Index");
            }
            ViewBag.BloggerID = new SelectList(db.Retrieve<Blogger>(null), "BloggerID", "Name", blog.BloggerID);
            return View(blog);
        }








Happy programming.....

      by Carmel Schvartzman


כתב: כרמל שוורצמן




Tuesday, July 1, 2014

Step by step how to send a cross-domain Ajax request

        By Carmel Schvartzman


In this tutorial we'll learn how to send a cross-domain Ajax HTTP request using javascript jQuery methods. We'll use the $.ajax() method to render just a sample XML response , fixing the "No 'Access-Control-Allow-Origin' header is present on the requested resource" error.

Let's say you have a web page which sends HTTP GET or HTTP POST requests to a web service (WCF endpoint or OData service) to load the data :





Everything works fine , provided that BOTH the client and the web services are in the SAME DOMAIN. The problem will arouse while the client and the server are hosted in DIFFERENT DOMAINS :





We got an  "No 'Access-Control-Allow-Origin' header is present on the requested resource" error, and there are "provisional" headers displayed.
Why? Because in the case of AJAX cross-domain requests, the browser sends some kind of "PRE-REQUEST" to  the web server, of the type of HTTP OPTIONS verb, informing that a CROSS-DOMAIN violation is being produced. Is then up to the web server to send or not a response to the web client.
That's because cross-domain HTTP requests started from scripts are subject to security restrictions. The 'CORS' (Cross Origin Resource Sharing) policy,  prevents access to methods and properties across DOMAINS, that means,  pages on different  web sites will not successfully retrieve data from some other domain, subdomain, or even internet protocol. For example, some resource loaded from  the domain http://AAAdomain.com)   makes a HTTP request for a resource on OTHER domain such as  http://BBBdomain.com . A web application can only make HTTP requests via AJAX to the domain to which it belongs, and not to other domains.
You can access to in-deep information about CORS policy in this web site.
To solve the  problem, we'll simply set the "Access-Control-Allow-Origin" header on our web server, setting it to "*" , in order to accept cross-domain AJAX HTTP requests from different domains.

Our Ajax request will be as follows:

 $.ajax(              {  

    crossDomain: true,

                url: url,
                type: "GET",
                contentType: "text/plain", 
                dataType: "xml",
                data: "",
                success: function (data)
                {                   
                    $(data).find('entry').each(function (index) {                         
                     
                        var id = $(this).find('BlogID').text();  
                        var title = $(this).find('Title').text();  
                        var text = $(this).find('Text').text();
                        var img = $(this).find('MainPicture').text();                        
                       
                    });                   
                                   },
                error: function (res) {
                    alert(res.status);
                }            });





And inside the <system.webServer> element at the web.config of the web server we'll set the headers to "*" :







<!--<httpProtocol>  --><!--THIS IS FOR CORS POLICY--><!--
      <customHeaders>

          <add name="Access-Control-Allow-Origin" value="*" />
          <add name="Access-Control-Allow-Headers" value="Content-Type" />
          <add name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" />
      </customHeaders>
  </httpProtocol>-->  </system.webServer>  



That's all we must get done, to enable cross-domain AJAX requests.

In this tutorial we've learned how to send a cross-domain Ajax request using javascript jQuery methods,  fixing the "No 'Access-Control-Allow-Origin' header is present on the requested resource" error.

That's all!! 
Happy programming.....

כתב: כרמל שוורצמן










Monday, June 16, 2014

Step by step how to fix the error "'The type initializer for 'System.Data.Services.Providers.ResourceType' threw an exception.'

       By Carmel Shvartzman

In this tutorial we'll learn how to fix the error "'The type initializer for 'System.Data.Services.Providers.ResourceType' threw an exception.' while deploying an ODATA WCF Data Service  in a web host
The error is caused because there is a specific version of an assembly missing. 
Open the references of your MVC Visual Studio app, those related to ODATA, and you'll see something like this : 
Microsoft.Data.Edm.dll    5.2.0.0
Microsoft.Data.OData.dll 5.2.0.0
System.Spatial.dll            5.2.0.0

Microsoft.Data.Services is a version 5.0.0.0 : but the version of the assemblies should be the same. If not so, there could be  functions missing and other problems of lack of fitness between them.
Open the Package Manager Console and enter the following expression, to put in sync the ASSEMBLY VERSIONS :

> Install-Package Microsoft.Data.Services -Version 5.2.0

This will bring the required DLL and remove the older version of the assembly.

You can also set in the web.config what will be  the new version of the assembly, but it is not required to do so:

<runtime>   <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">     <dependentAssembly>       <assemblyIdentity name="Microsoft.Data.Services"                     publicKeyToken="XXXX" />             <bindingRedirect oldVersion="1.0.0.0-5.0.0.0" newVersion="5.2.0.0" />     </dependentAssembly>    </assemblyBinding> </runtime>

Just change the version to the one you need : 5.2.0.0!!


Happy programming.....


כתב: כרמל שוורצמן

Step by step how to fix the error "Could not load file or assembly 'Microsoft.Data.Services, Version=5.0.0.0'"

       By Carmel Shvartzman

In this tutorial we'll learn how to fix the error "Could not load file or assembly 'Microsoft.Data.Services, Version=5.0.0.0'" in an Asp.Net MVC application
This error is thrown in case of a reference in your application, that points to the 5.0.0.0 version of the Microsoft.Data.Services assembly.
The error appears as this : 

  First i thought that the problem was in the web.config:
<dependentAssembly>
<assemblyIdentity name="Microsoft.Data.Services" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-5.0.0.0" newVersion="5.0.2.0" />
</dependentAssembly>

But as can be seen, there was explicitly stated to use the version 5.2.0.0 of the assembly.
Then i remembered that at the creation of the data Service, there is a definition  of the version of the   Microsoft.Data.Services  assembly to be loaded:






Just change the version to the one you need : 5.2.0.0, & that's all!!


Happy programming.....


כתב: כרמל שוורצמן