Showing posts with label asp.net-mvc-5. Show all posts
Showing posts with label asp.net-mvc-5. Show all posts

Wednesday, September 6, 2017

AJAX error not returning jqXHR.responseText.modelState when using custom dll

Leave a Comment

I am using an asp.net webapi controller, and in my project I have a dll that I built myself. The dll is being used to validate if the person that the user is typing in actually exists.

Here is my controller method:

// POST: api/EventsAPI [ResponseType(typeof(Event))] public IHttpActionResult PostEvent(Event @event) {     if (!ModelState.IsValid)     {         return BadRequest(ModelState);     }      if (@event.DateEndOfEvent < @event.DateOfEvent) // successfully returns error.modelState (in view code)     {         ModelState.AddModelError("DateEndOfEvent", "End Date Cannot Be Before Start Date!");         return BadRequest(ModelState);     }      if (!EmpData.IsValid(@event.PersonWorkedOne)) // returns error.modelState as undefined (in view code)     {         ModelState.AddModelError("PersonWorkedOne", "This person does not exist!");         return BadRequest(ModelState);     }      if (!string.IsNullOrWhiteSpace(@event.PersonWorkedTwo))     {         if (!EmpData.IsValid(@event.PersonWorkedTwo)) // returns error.modelState as undefined (in view code)         {             ModelState.AddModelError("PersonWorkedTwo", "This persondoes not exist!");             return BadRequest(ModelState);         }     }      db.Event.Add(@event);     db.SaveChanges();      return CreatedAtRoute("DefaultApi", new { id = @event.Id }, @event); } 

Now the two conditional statements above that have EmpData.. EmpData is from my dll.

Here is the ajax code in my view:

$("form").data("validator").settings.submitHandler =     function(form) {         $.ajax({             method: "POST",             url: infoGetUrl,             data: $("form").serialize(),             success: function() {                 toastr.options = {                     onHidden: function () {                         window.location.href = newUrl;                     },                     timeOut: 3000                 }                 toastr.success("Event successfully created.");             },             error: function (jqXHR, textStatus, errorThrown) {                 var status = capitalizeFirstLetter(textStatus);                 var error = $.parseJSON(jqXHR.responseText);                  var modelState = error.modelState;                 console.log(modelState);                 $.each(modelState,                     function (key, value) {                         var id = "";                         if (key === "$id") {                             id = "#" +                                 key.replace('$', '').substr(0, 1).toUpperCase() +                                 key.substr(2);                         } else {                             id = "#" +                                 key.replace('$', '').substr(0, 1).toUpperCase() +                                 key.substr(1);                             var status = capitalizeFirstLetter(textStatus);                             console.log(key);                              toastr.error(status + " - " + modelState[key]);                         }                         var input = $(id);                         console.log(id); // result is #id                         if (input) { // if element exists                             input.addClass('input-validation-error');                         }                     });             }         });     } 

Now, in the controller when I purposefully test to get the error message concering the end date being before the start date, I receive error.modelState. But when I purposefully test to get the error message saying that a person does not exist... I do not get error.modelState.. that returns as undefined.

Does returning ModelState not work when using custom DLL?

Any help is appreciated.

1 Answers

Answers 1

I was able to figure this out with the help of ADyson. I edited my DLL file to return just a bool object.

Originally if what I was checking in IsValid was anything other than true, then I would throw an exception which was causing this error.

So taking the exception part out and just returning either true or false worked.

Original

public static bool IsValid(string person) {     bool empExists = lstAllEmps.Any(x => x.IDNumber == person);      if (empExists)     {         return empExists;     }     else     {         var exceptionMessage = string.Format("The person, {0}, does not exist!", person);         throw new ArgumentException(exceptionMessage, person);     } } 

New

public static bool IsValid(string person) {     bool empExists = lstAllEmps.Any(x => x.IDNum == person);       return empExists; } 
Read More

Wednesday, August 30, 2017

Go To Controller shows “Unable to find a matching controller.” error

Leave a Comment

In VS 2015, for my Web.API project, I installed MVC 5 from nuget via npm. This installation added references and generated web.config file under Views folder.

I added new Controller with generated CRUD functions. When I right click and go to View on action it goes with no problem. But reverse action does not work. If I navigate to view via browser it works as well. Web app compiles as well.

Is there any way for me to fix this navigation problem in VS? Did I forget to add something?

Following Works

this works with no problem

Following gives Error:

this does not work

error

P.S: If I create brand new sample MVC 5 app both actions work as expected, this only happens Web.API project where MVC 5 added later on via nuget.

4 Answers

Answers 1

This happened to me once. Delete the view and try adding the view again by right clicking on the controller action method and clicking Add View again. I think it would solve the problem

Answers 2

There appears to be a default shortcut key Ctrl-M then Ctrl-G.

This will automatically switch between the controller and view page. If you're on the controller/action it will switch to the view and vice versa.

Answers 3

It happens while the controller or view may be not exactly in the controller folder or view folder respectively. It may contain an additional folder. You can solve this issue through adding a new view and delete the old view.

Answers 4

YOU can try it like this, Add Controller first ,then and the View By hands,then you can get the right page what you want ?

Read More

Tuesday, August 22, 2017

MVC 5 - Precompiling views only works from the command prompt

Leave a Comment

I have a strange issue that hopefully someone can help me with. I got a new laptop and I'm trying to publish the same ASP.NET MVC 5 project on the new machine with precompiled views. However, when I do a publish with "Precompile during publishing" option checked, it does not create the precompiled views. Now, if I copy the exact command that it ran and run it in the Command Prompt, the precompiled views are created.

Here's the details. Both machine have Windows 10 Anniversary Update (Version 1607) with Visual Studio 2013 Update 5. Publishing the app on the old machine with the same publish profile generates the precompiled views. On the new machine, publishing from the "Publish Web" dialog runs without errors, but no precompiled views are generated. I then copied this exact command to the Command Prompt that VS used to precompile:

C:\windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe -v / -p C:\MyApp\obj\Release\AspnetCompileMerge\Source -c C:\MyApp\obj\Release\AspnetCompileMerge\TempBuildDir 

When I ran it, it created the precompiled views in the TempBuildDir\bin directory!

The only difference I can think of between the machines are the Windows Updates.

Any ideas? Thanks.

1 Answers

Answers 1

Do you use the x64 verson of Windows?

Also you can try set $(AspnetCompilerPath) manually:

msbuild.exe /p:AspnetCompilerPath="C:\windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe" 

or add it to your project:

<PropertyGroup>   <AspnetCompilerPath Condition=" '$(AspnetCompilerPath)'=='' " >C:\windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe</AspnetCompilerPath> </PropertyGroup> 

I've made this assumption, because the Microsoft.Web.Publishing.AspNetCompileMerge.targets file contains the string:

 We can't use the in-place aspnet_compiler because it will output to the aspnet temp folder which is only suiteable to run on the current machine. 
Read More

Friday, June 23, 2017

MVC WebGrid paging action changing upon navigation

Leave a Comment

I'm working in an MVC app that is using a webgrid with paging. The grid itself is rendered in a partial view called _Results.cshtml and is rendered in a div on the index.cshtml page using

Html.RenderPartial("_Results", Model.Results); 

The partial grid as well as a few other form controls on index.cshtml are wrapped in a form called ResultsAction using:

@using (Ajax.BeginForm("ResultsAction", "Results", new AjaxOptions..... 

When intially navigating to the index.cshtml, the grid populates as expected and hovering over any of the paging links correctly display:

http://localhost/ResultsAction?page=<page#> 

Each row in the grid has a link to a detail page. This works as expected and the detail page has a link to return to the result grid using:

@Html.ActionLink("Return To Results", "Index", "Results") 

Now the problem. This redirects me back to the Index.cshtml just fine but now when I hover over any of the paging links in the grid, they incorrectly are using:

http://localhost/Index?page=<page#> 

Which is the wrong controller action so paging no longer functions. My understanding was the paging links should issue a Get using the form name as the action, yet it's being overridden somehow when I navigate to detail then back again. Does anyone know what's causing this behavior or how I can specify the paging links to always use the same controller action?

EDIT: Posting code of partial view as requested:

@model IEnumerable<ispPR_GetInquiryRecords_Result>  @{     Layout = null; }  <input id="searchListCnt" type="hidden" value="@Model.Count()" />  <div id="gridSearch">  @{      var grid = new WebGrid(selectionFieldName: "SelectedRow", canSort: false, canPage: true, rowsPerPage: 10, ajaxUpdateContainerId: "gridSearch");  var virtualCount = Model != null && Model.Count() > 0 ? Model.First().VirtualCount : 0;  grid.Bind(Model, rowCount: (int)virtualCount, autoSortAndPage: false); }      <div id="gridContent">     @grid.GetHtml(     htmlAttributes: new { id = "inqgrid" },     tableStyle: "webGrid",                   fillEmptyRows: false,                   footerStyle: "gridFooter",                   displayHeader: true,                   alternatingRowStyle: "alt",                   selectedRowStyle: "select",                   mode: WebGridPagerModes.All,                   columns: grid.Columns(                   grid.Column("PriceStatus",header:"Price Status"),                       grid.Column("CustomerName","Customer Name"),                       grid.Column("EndUserName", "End User"),                       grid.Column("ContractNumber","Contract"),                       grid.Column("PriceLevel", "Level"),                       grid.Column("ProductDescription", "Product Code"),                         grid.Column(                                              header: "Break Qty",                                                                        format: @<text>@item.QuantityBreak.ToString() / @item.QuantityBreakUOM </text>                                          ),                        grid.Column("BeginDate", "Begin Date", format: item =>string.Format("{0:d}", item.BeginDate)),                       grid.Column("EndDate","End Date",format: item =>string.Format("{0:d}", item.EndDate)),                          grid.Column(                                         header: "Price in PricingUOM",                                         format: item =>                                             {                                                 var res = Html.FormatToDecimals((decimal)item.PriceInPricingUOM, (int)item.Numdecimals);                                                  switch ((bool)@item.HasDetail)                                                 {                                                     case true:                                                           return Html.ActionLink(res + " / " + (string)item.PricingUOM, "InquiryDetails", new { @id = @item.PriceMasterID }, new { @class = "item-link2", @id = "lnk_" + @item.PriceMasterID });                                                     case false:                                                         return Html.ActionLink(res+ " / " + (string)item.PricingUOM, null, null, new { onclick = "return NoDetailsDialog('" + @item.NoDetailReason + "')" });                                                   }                                                  return null;                                             }                                             ),                        grid.Column(                                             header: "Price Alt UOM",                                             format: @<text>@Html.FormatToDecimals((decimal)item.PriceInOrderUOM, (int)item.Numdecimals) / @item.OrderUOM </text>                                          ),                        grid.Column("Rolling12", "Rolling 12 Sales", format: @<text>@String.Format("{0:c0}", @item.Rolling12) </text>),                       grid.Column("CMPercent", "Net CM ", format: @<text>@String.Format("{0:0.00} %", @item.CMPercent * 100) </text>)       ))   </div>     </div>  <script type="text/javascript">     function NoDetailsDialog(message) {          alert(message);         return false;     } </script> 

2 Answers

Answers 1

You can use datatables. Please let me know how you progress with datatables and I can be available to help you through it, I can even assist with razor syntax:

nuget DataTabes.net jquery plugin

bundles.Add(new StyleBundle("~/Content/CssGrid").Include(                     "~/Content/DataTables/css/jquery.dataTables.min.css"));  bundles.Add(new ScriptBundle("~/bundles/JSGrid").Include(                     "~/Scripts/DataTables/jquery.dataTables.min.js")); 

JavaScript:

//perform tasks like initialize fields, show popup, and post to server function DeleteMe() function EditMe() function Add() 

Page:

$(document).ready(function() {     $('#theDataTable').DataTable();  } );  </script>  //button to show popup for add/edit here <table id="theDataTable" class="display table table-striped table-bordered">                 <thead>                     <tr>                         <th>Field Name A                         </th>                         <th>Field Name B                         </th>                         <th>Field Name C                         </th>                          </th>                         <th>Delete                         </th>                         <th>Edit                         </th>                 </thead>                 <tbody>                     <%  int rowCount = 0;                         foreach (AClass item in Model.AClassList)                         { %>                     <tr id="<%:rowCount%>">                         <td><%:item.FieldA%></td>                         <td><%:item.FieldB%></td>                         <td><%:item.FieldC%></td>                         <td>                             <a href="#" title="Delete" class="btn btn-default btn-xs btn-block"                                 onclick="return DeleteMe('<%:item.Id%>')">Delete</a>                         </td>                         <td>                             <a href="#" title="Edit" class="btn btn-default btn-xs btn-block"                                 onclick="return EditMe('',                                       '<%:item.FieldA %>',                                      '<%: Html.Encode(item.FieldB) %>',                                       '<%: Html.Encode(item.FieldC) %>')">Edit</a>                         </td>                         <% rowCount++;                         } %>                     </tr>                 </tbody>             </table> 

Example that we can make prettier

Answers 2

I have come across the same problem before. In my case it ended up being something to do with the MVC view resolver being scoped to the wrong folder due to calling a different controller than the one that had been used to construct the view which I was making the call in.

I know that's not much help, and it does seem peculiar as you have explicitly stated the controller name in your BeginForm statement. I had my mentor resolve the issue for me in the end, he did so by trial and error just commenting out the various lines until the problem was isolated.

Read More

Monday, June 5, 2017

Sqlite on Azure: The server was not found or was not accessible

Leave a Comment

I am using SQLite in an Asp.Net MVC 5 project which is working fine.

I uploaded the application to Microsoft Azure and I got the following error:

A network-related or instance-specific error occurred while establishing a connection to SQL Server.  The server was not found or was not accessible.  Verify that the instance name is correct and that SQL Server is configured to allow remote connections.  (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified) 

In Azure I added the following connection string:

Data Source=D:\home\site\wwwroot\Data\MyDatabase.sqlite;Password=pass 

Since there is no SqlLite database option I selected Custom: enter image description here

I checked using Azure Kudu and the file is in the right path ...

However, when I run the application I keep getting the error.

Does anyone knows how to solve this?

UPDATE

My Entity Framework class is the following:

[DbConfigurationType(typeof(Configuration))] public class Context : DbContext, IDbContext {    public Context() {     Configuration.With(x => {               x.AutoDetectChangesEnabled = true;       x.LazyLoadingEnabled = false;       x.ProxyCreationEnabled = true;       x.ValidateOnSaveEnabled = true;     });   }    public DbSet<Post> Posts { get; set; }   public DbSet<Tag> Tags { get; set; }    protected override void OnModelCreating(DbModelBuilder builder) {   }  }  public class Configuration : DbConfiguration {   public Configuration() {     SetDatabaseInitializer<Context>(null);         SetProviderServices(SqlProviderServices.ProviderInvariantName, SqlProviderServices.Instance);   } } 

And I have the following on Global.asax:

AppDomain.CurrentDomain.SetData("DataDirectory", AppDomain.CurrentDomain.BaseDirectory + "Data");  builder.RegisterType<Context>().As<IDbContext>().InstancePerRequest(); 

The connection string in Web.Config is:

<connectionStrings>   <add name="Context" providerName="System.Data.SQLite" connectionString="Data Source=|DataDirectory|\MyDatabase.sqlite;Version=3;Password=pass" /> </connectionStrings> 

1 Answers

Answers 1

I found the solution. Instead of defining a ConnectionString in Azure I need to define an Application Setting in Azure for DataDirectory where the value is the directory in Azure where the database is ...

The absolute path of the database location in Azure can be found using Kudu's Debug Console.

Following my example the DataDirectory application settings would have:

Key: DataDirectory Value: D:\home\site\wwwroot\Data 
Read More

Wednesday, April 26, 2017

Why do I keep getting HTTP 403 error on shared hosting?

Leave a Comment

I have an MVC 5 app, developed under .NET 4.6 and MVC 5.2.3 that works 100% when I debug it in Chrome and Edge on my machine. When I deploy to shared hosting at my ISP, it gives the following error on every request after the very first one, which succeeds and shows the login page.

403 - Forbidden: Access is denied. You do not have permission to view this directory or page using the credentials that you supplied.

Then if I clear a cookie called .AspNet.ApplicationCookie from Chrome, then the next request succeeds, but the cookie is back and all subsequent requests fail in the same manner.

I am not using application state in any of my own code, and the only packages I have added to those that come with the standard VS2015 project template are:

AutoMapper elmah.corelibrary Elmah.Mvc Unity Unity.Mvc5 

If I've done this correctly, when I check for cookies in Edge, there no such cookie, only the __RequestVerificationToken, which plays no role (outside the scope of this question) in Chrome.

NOTE: I have now changed hosting providers, and instead of get a 403 on nearly every request since after the first since app startup, I now get redirected to my login page about every 1 to 2 minutes. It looks like one provider is handling my lack of auth better, but have a strong suspicion that both problems are due to loss of session. This is probably due to limited resources on shared hosting, so I've tried moving to storing session on SQL Server but it makes no difference, and Elamh shows no errors, so I don't know if my session move worked.

1 Answers

Answers 1

I think you are using the new dotnet core Cookie middleware. This middleware encrypts your session data inside the cookie value.

The problem is that the encryption/decryption is done based on a key which is unique per application-host (based on machine key). So if your request lands on a different instance than where your session cookie was encrypted, it is unable to decrypt your cookie, and thus thinks you are not authenticated!

You can change this behavior by implementing a different backing store (like redis or sql server).

Read the documentation on how to do this: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/cookie

Read More

Sunday, April 16, 2017

Passing viewmodel between partial views MVC5

Leave a Comment

I have a main view and two partial views. I need to be able to populate the viewmodel with the values in my first partial view and pass the viewmodel to the second partial view on click of the button. The button is in the second partial view. I have written a javascript function to do that but the viewmodel is empty when I check the controller method. As you you can see in the screenshot below the services box is the second partial view

First Partial view

enter image description here

Second Partial View

@model CC.GRP.MCRequest.ViewModels.NewRequestViewModel  <div id="NewRequest">     <h1>Services</h1>      @using (Html.BeginForm())     {          @Html.LabelFor(model => model.ProjectName, htmlAttributes: new { @class = "control-label col-md-5" })         @Html.EditorFor(model => model.ProjectName, new { htmlAttributes = new { @class = "form-control", style = "width:100%" } })          <input type="submit" value="Save" class="btn btn-default" onclick="mapInit()" />     }   </div>   <script type="text/javascript">      function mapInit() {         $.ajax({             url: '@Url.Action("Service", "request")',             // datatype: "json",             data: $('form').serialize(), // update this             type: "POST",             // contentType: 'application/json; charset=utf-8'         });     }   </script> 

Controller

[HttpPost] public PartialViewResult Service(NewRequestViewModel model) {     return PartialView("_NewService", model); } 

2 Answers

Answers 1

Here is my suggestion to you how to resolve your task:

  1. You have to change the type of your button on the Second partial view form to the button type: <input type="button" value="Save" class="btn btn-default" onclick="mapInit()" /> This step is necessary not to clean your form when an original submit-event works out after your ajax method.
  2. In your mapInit function you should add a property success and write a function there to update your Second partial form by hand this way:

    function mapInit() {     $.ajax({         url: '@Url.Action("Service", "request")',         // datatype: "json",         data: $('form').serialize(), // update this         type: "POST",         success: function (data)         {             var html = $(data).find('form').html();             $('#NewRequest').find('form').html(html);         }     }); } 

Thus, providing that your First partial form has the same fields, you'll be able to fill your second form with what you want.

Answers 2

1) Create a get or post action for your partial view.This will get your posted model as parameter and returns second partial view.

2) Modify the BeginForm field of partial view in UI and add OnSuccess event.(eg Handel OnSuccess)

3) Create Jquery method to get request on success and replace the first partial view content with second one in UI.(eg: $('#PartialView1Container').html(result);)

Read More

Monday, February 27, 2017

MvcBuildViews true causes “'/temp' is not a valid IIS application” error

Leave a Comment

After setting MvcBuildViews to true in my .csproj file in order to have the views compile during build, I get the following error:

'/temp' is not a valid IIS application

I presume that the '/temp' that this is referring to is the path where the views will be compiled. Here's the relevant section in the .csproj file:

<Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">     <AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" /> </Target> 

I use full IIS to serve up this MVC 5 website on my local machine (haven't tried this on a remote server yet). Do I need to set something up in IIS to make MvcBuildViews work correctly?

1 Answers

Answers 1

See this, I guess you've to make IIS virtual directory names temp to point to this application.

Read More

Saturday, September 24, 2016

Where can I load the user information to the session in ASP.NET MVC 5 with windows authentication?

Leave a Comment

I want to use the ASP.NET MVC 5 for my web app. I need use the windows authentication.

If I use the windows authentication where is the best place for reading user information (userid and roles) and store its to the Session?

I have the method for getting the user information by username from the database like this:

public class CurrentUser     {         public int UserId { get; set; }          public string UserName { get; set; }          public Roles Roles { get; set; }     }      public enum Roles     {         Administrator,         Editor,         Reader     }      public class AuthService     {         public CurrentUser GetUserInfo(string userName)         {             var currentUser = new CurrentUser();              //load from DB              return currentUser;         }     } 

1 Answers

Answers 1

First and foremost: never, never, never store user details in the session. Seriously. Just don't do it.

If you're using Windows Auth, the user is in AD. You have use AD to get the user information. Microsoft has an MSDN article describing how this should be done.

The long and short is that you create a subclass of UserIdentity and extend it with the additional properties you want to return on the user:

[DirectoryRdnPrefix("CN")] [DirectoryObjectClass("inetOrgPerson")] public class InetOrgPerson : UserPrincipal {     // Inplement the constructor using the base class constructor.      public InetOrgPerson(PrincipalContext context) : base(context)     {     }      // Implement the constructor with initialization parameters.         public InetOrgPerson(PrincipalContext context,                           string samAccountName,                           string password,                           bool enabled)                          : base(context,                                  samAccountName,                                  password,                                  enabled)     {     }      InetOrgPersonSearchFilter searchFilter;      new public InetOrgPersonSearchFilter AdvancedSearchFilter     {         get         {             if ( null == searchFilter )                 searchFilter = new InetOrgPersonSearchFilter(this);              return searchFilter;         }     }      // Create the mobile phone property.         [DirectoryProperty("mobile")]     public string MobilePhone     {         get         {             if (ExtensionGet("mobile").Length != 1)                 return null;              return (string)ExtensionGet("mobile")[0];         }          set         {             ExtensionSet( "mobile", value );         }     }      ... } 

In the example code above, a property is added to bind to the AD's user's mobile field. This is done by implementing the property as shown utilizing ExtensionSet, and then annotating the property with the DirectoryProperty attribute to tell it what field it binds to.

The DirectoryRdnPrefix and DirectoryObjectClass attributes on the class need to line up with how your AD is set up.

Once this is implemented, then you will be able to get at the values simply by referencing them off User.Identity. For example, User.Identity.MobilePhone would return the mobile field from AD for the user.

Read More

Friday, April 29, 2016

Search for view files in a custom location only for Specified Area in MVC 5

Leave a Comment

I'm looking to override the 'ViewEngine' for MVC5 in a way that first, it find my pages.. which already i failed.

Second, It only operate on a single Area {root}/{area}/{controller}/{action}/{etc.}

as so far as i googled it, i found several topic and answers, but they didn't fit my need. so i rather to ask it here, maybe i'm wrong with something...

public class CustomAreaViewEngine:RazorViewEngine {     public CustomAreaViewEngine()     {         var viewLocations = new[]         {             "~/App/pages/{1}/{0}.cshtml",             "~/App/pages/{1}/{0}.vbhtml"         };         AreaMasterLocationFormats = viewLocations;         AreaPartialViewLocationFormats = viewLocations;         AreaViewLocationFormats = viewLocations;     }      public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)     {          var viewEngineResult = base.FindPartialView(controllerContext, partialViewName, useCache);         return viewEngineResult;     }      public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)     {         controllerContext.RouteData.Values["controller"] = controllerContext.RouteData.Values["controller"].ToString().ToLower();          var viewEngineResult = base.FindView(controllerContext, viewName, masterName, useCache);         return viewEngineResult;     } } 

The method 'FindView' returns empty [first problem]

Global Config:

AreaRegistration.RegisterAllAreas(); ViewEngines.Engines.Add(new CustomAreaViewEngine()); // Look View Inside App/Pages/{1}/{0}.cshtml/.vbhtml 

My Hierarchy

Root --/App --/--/pages --/--/shared (but not that shared) --/... --/Area --/--/View --/--/--/Controller --/--/--/View(MVC BASED HIERARCHY, I Don't want to use in most case, and redirect to App) --/--/--/... --/--/... --/Controller --/View --/--/...(MVC BASED HIERARCHY) --/... 

EDITS:


EDIT1:


Changes i did due to @James Ellis-Jones answers:

Images: My Route Config: My Route Config Area Provided Route Config: Area Provided Route Config Global Config: Global Config My View Engine: My View Engine

still when i use http://localhost:1422/view/home/index i receive an error, which exist in my other home (View, related to the main controller, not the area controller.) it bring a wrong file.

Another Issue I Figured Out, Which Didn't Worked Too

My namespaces was wrong in last edit, and i changed them, but it didn't worked out too.

namespaces: new[] { "RavisHSB.Areas.View.Controllers" } 

EDIT2:


Changes i did due to @CarlosFernández answers:

I add ViewEngines.Engines.Clear(); it somehow went one step ahead. but still doesn't work.

New Global.aspx: My Global.aspx And i face this new error: The new Error

2 Answers

Answers 1

Try this: in RouteConfig.cs where you are setting up the route which links to a controller which you want to find the custom view location, add this:

var route = routes.MapRoute(<route params here>); route.DataTokens["area"] = "AreaName"; 

This will tell MVC that when you follow this route, you are going into area 'AreaName'. Then it will subsequently look for views in that area. Your custom ViewEngine will only affect view locations when MVC is looking for them in some area. Otherwise it won't have any effect, as the location format lists for areas are the only ones it overrides.

Answers 2

Try to customize this code for your engine

using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Web; using System.Web.Mvc;  namespace Partikan.Tuba.Core {      /*                                              TubaPortal Razor ViewEngine      *       * Path for Themes : ~/Site/Themes/{ThemeName}/Skin/{Culture}/{SkinName} ---> ~/Site/Themes/Default/Skin/fa-IR/default.csHtml      *  themeName, culture, name, controllerName, modulePath ,area      *       *       *       *       */      public class TubaPortalRazorViewEngine : RazorViewEngine     {         private static readonly List<string> EmptyLocations;          public TubaPortalRazorViewEngine()         {               MasterLocationFormats = new[]                 {                     "~/Site/Themes/{0}/Skin/{1}/{2}.cshtml",                     "~/Site/Themes/{0}/Skin/{2}.cshtml",                     "~/Views/Shared/{2}.cshtml"                 };             PartialViewLocationFormats = new[]                 {                     "~/Views/{1}/{0}.cshtml",                     "~/Views/Shared/{0}.cshtml",                                         "~/Site/Themes/{0}/Container/{2}.cshtml",                     "~/Plugins/{2}/{2}.cshtml",                     "~/Views/{3}/{2}.cshtml",                     "~/Views/Shared/{2}.cshtml"                 };              ViewLocationFormats = new[]                 {                                        "~/Site/Themes/{0}/Container/{2}.cshtml",                     "~/Plugins/{2}/{2}.cshtml",                     "~/Views/{3}/{2}.cshtml",                     "~/Views/Shared/{2}.cshtml"                 };              AreaViewLocationFormats = new[]                 {                     "~/Areas/{5}/Views/{3}/{2}.cshtml",                     "~/Areas/{5}/Views/Shared/{2}.cshtml"                 };             AreaMasterLocationFormats = new[]                 {                     "~/Areas/{5}/Views/{3}/{2}.cshtml",                     "~/Areas/{5}/Views/Shared/{2}.cshtml"                 };             AreaPartialViewLocationFormats = new[]                 {                     "~/Areas/{5}/Views/{3}/{2}.cshtml",                     "~/Areas/{5}/Views/Shared/{2}.cshtml"                 };             }          private static string GetThemeToUse(ControllerContext controllerContext)         {             if (controllerContext.HttpContext.Items == null) return "";             var themeName = controllerContext.HttpContext.Items["themeName"] == null ? "" :                 controllerContext.HttpContext.Items["themeName"] as string;                    return String.Format("{0}", themeName);         }         private static string GetCulture(ControllerContext controllerContext)         {             if (controllerContext.HttpContext.Items != null)             {                  var culture = controllerContext.HttpContext.Items["culture"] as string;                 if (string.IsNullOrEmpty(culture)) culture = "fa-IR";                 return String.Format("{0}", culture);             }             return "fa-IR";         }          protected override bool FileExists(ControllerContext controllerContext, string virtualPath)         {             try             {                 return System.IO.File.Exists(controllerContext.HttpContext.Server.MapPath(virtualPath));             }             catch (HttpException exception)             {                 if (exception.GetHttpCode() != 0x194)                 {                     throw;                 }                 return false;             }             catch             {                 return false;             }         }          public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)         {             var strArray = new List<string>();             var strArray2 = new List<string>();                        if (controllerContext == null)             {                 throw new ArgumentNullException("controllerContext");             }             if (string.IsNullOrEmpty(viewName))             {                 throw new ArgumentException("viewName must be specified.", "viewName");             }                var themeName = GetThemeToUse(controllerContext);              var culture = GetCulture(controllerContext);              var controllerName = controllerContext.RouteData.GetRequiredString("controller");             var modulePath = controllerContext.RouteData.Values.Keys.Contains("ModulePath") ? controllerContext.RouteData.GetRequiredString("ModulePath") : "";             var viewPath = "";              var viewLocation = ViewLocationFormats;             var masterLocation = MasterLocationFormats;             var area = "";             if (controllerContext.RouteData.DataTokens.Keys.Any(x => x.ToLower() == "area"))             {                 area = controllerContext.RouteData.DataTokens.FirstOrDefault(x => x.Key.ToLower() == "area").Value.ToString();                  viewLocation = AreaViewLocationFormats;                 masterLocation = AreaMasterLocationFormats;             }              if (IsExternalWidgetView(viewName))             {                 viewPath = viewName;             }             else             {                 viewPath = GetPath(controllerContext, viewLocation, area, viewName, themeName, controllerName, culture, modulePath, "TubaSite_View", useCache, strArray);             }                var masterPath = GetPath(controllerContext, masterLocation, area, masterName, themeName, controllerName, culture, modulePath, "TubaSite_Master", useCache, strArray2);              if (!string.IsNullOrEmpty(viewPath) && (!string.IsNullOrEmpty(masterPath) || string.IsNullOrEmpty(masterName)))             {                 return new ViewEngineResult(this.CreateView(controllerContext, viewPath, masterPath), this);             }             if (string.IsNullOrEmpty(masterPath) && strArray == null)             {                 throw new Exception(String.Format("Skin {0} {1} in {2} Not Found .", themeName, masterName, masterPath));             }             if (string.IsNullOrEmpty(viewPath))             {                 throw new Exception(String.Format("Page Not Found - {0} {1} {2}", themeName, masterName, masterPath));             }             return new ViewEngineResult(strArray.Union<string>(strArray2));         }         public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)         {             var strArray = new List<string>();             if (controllerContext == null)             {                 throw new ArgumentNullException("controllerContext");             }             if (string.IsNullOrEmpty(partialViewName))             {                 throw new ArgumentException("partialViewName must be specified.", "partialViewName");             }               var themeName = GetThemeToUse(controllerContext);             var modulePath = controllerContext.RouteData.Values.Keys.Contains("ModulePath") ? controllerContext.RouteData.GetRequiredString("ModulePath") : "";              var requiredString = controllerContext.RouteData.GetRequiredString("controller");              var partialViewLocation = PartialViewLocationFormats;             var area = "";             if (controllerContext.RouteData.DataTokens.Keys.Any(x => x.ToLower() == "area"))             {                 area = controllerContext.RouteData.DataTokens.FirstOrDefault(x => x.Key.ToLower() == "area").Value.ToString();                 partialViewLocation = AreaPartialViewLocationFormats.Union(PartialViewLocationFormats).ToArray();             }              var partialViewPath = "";             if (IsExternalWidgetView(partialViewName))             {                 partialViewPath = partialViewName;             }             else             {                 partialViewPath = GetPath(controllerContext, partialViewLocation, area, partialViewName, themeName, requiredString, "fa-IR", modulePath, "TubaSite_Partial", false, strArray);             }             return string.IsNullOrEmpty(partialViewPath) ? new ViewEngineResult(strArray) : new ViewEngineResult(CreatePartialView(controllerContext, partialViewPath), this);         }           private string GetPath(ControllerContext controllerContext, string[] locations, string area,                 string name, string themeName, string controllerName, string culture, string modulePath,                 string cacheKeyPrefix, bool useCache, List<string> searchedLocations)         {             searchedLocations = EmptyLocations;             if (string.IsNullOrEmpty(name))             {                 return string.Empty;             }              if ((locations == null) || (locations.Length == 0))             {                 throw new InvalidOperationException("هـیچ مسـیـری بـرای جستجو تعریف نشده است.");             }              var flag = IsSpecificPath(name);             var key = CreateCacheKey(cacheKeyPrefix, name, flag ? string.Empty : controllerName, themeName);             if (useCache)             {                 var viewLocation = ViewLocationCache.GetViewLocation(controllerContext.HttpContext, key);                 if (viewLocation != null)                 {                     return viewLocation;                 }             }             if (!flag)             {                 return string.IsNullOrEmpty(culture) ?                         GetPathFromGeneralName(controllerContext, locations, area, name, controllerName, themeName,  modulePath, key, searchedLocations) :                         GetPathFromGeneralName(controllerContext, locations, area, name, controllerName, themeName, culture, modulePath, key, searchedLocations);              }             return GetPathFromSpecificName(controllerContext, name, key, searchedLocations);         }          private static bool IsExternalWidgetView(string name)         {              return name.StartsWith("~/ExternalWidget", StringComparison.InvariantCultureIgnoreCase);         }          private static bool IsSpecificPath(string name)         {             var ch = name[0];             if (ch != '~')             {                 return (ch == '/');             }             return true;         }          private string CreateCacheKey(string prefix, string name, string controllerName, string themeName)         {             return string.Format(CultureInfo.InvariantCulture,                     ":ViewCacheEntry:{0}:{1}:{2}:{3}:{4}", GetType().AssemblyQualifiedName, prefix, name, controllerName, themeName);         }          private string GetPathFromGeneralName(ControllerContext controllerContext, IEnumerable<string> locations, string area, string name,                 string controllerName, string themeName,  string culture, string modulePath, string cacheKey, List<string> searchedLocations)         {             if (locations == null) throw new ArgumentNullException("locations");             if (searchedLocations == null) searchedLocations = new List<string>();              var virtualPath = string.Empty;                      var locationData =                 locations.Select(                     t =>                     string.Format(CultureInfo.InvariantCulture, t,                                                 string.IsNullOrEmpty(culture)                                                     ? new object[] { name, controllerName }                                                     : new object[] {  themeName, culture, name, controllerName, modulePath, area })).ToList();             foreach (var str2 in locationData)             {                 if (FileExists(controllerContext, str2))                 {                     virtualPath = str2;                     ViewLocationCache.InsertViewLocation(controllerContext.HttpContext, cacheKey, virtualPath);                     return virtualPath;                 }                 searchedLocations.Add(str2);             }             return virtualPath;         }          private string GetPathFromGeneralName(ControllerContext controllerContext, IEnumerable<string> locations, string area, string name,                 string controllerName, string themeName,  string modulePath, string cacheKey, List<string> searchedLocations)         {             return GetPathFromGeneralName(controllerContext, locations, area, name, controllerName, themeName, "", modulePath, cacheKey, searchedLocations);         }          private string GetPathFromSpecificName(ControllerContext controllerContext, string name, string cacheKey, List<string> searchedLocations)         {             var virtualPath = name;             if (!FileExists(controllerContext, name))             {                 virtualPath = string.Empty;                 searchedLocations = new List<string>() { name };             }             ViewLocationCache.InsertViewLocation(controllerContext.HttpContext, cacheKey, virtualPath);             return virtualPath;         }     }  } 
Read More

Thursday, April 28, 2016

Visual Studio 2015 MVC Project Template Access Denied

Leave a Comment

I've created a very simple MVC application in VS2015 which has some basic CSS styling and some HTML to get an application off the ground more quickly.

The application runs perfectly.

I've exported this as a template using File -> Export Template...

I then created a brand new project based off this project type. So far so good. But, now when I run the newly created project I get a blank page with "Access Denied" (see image).

I've been going over the template project and the new project with a fine tooth comb and I can't find any differences. Why would one work but the other give an access denied? I am out of ideas, any help is appreciated.

Access Denied

EDIT:

After more research I have found the cause of the problem, but not a solution.

It seems that the project template has "Anonymous Authentication" as Disabled, and has "Windows Authentication" set to Enabled in the project settings. However when I create a project based on the template these values are flipped and thus causes the Access Denied.

Here's an image of the project settings in the template:

enter image description here

Here's an image of the project settings in the "new" project:

enter image description here

Note that both Authentication settings are flipped. Can anyone tell me how to get this to not happen?

Edit 2:

As suggested, the applicationhost.config files are different which is causing the above problem. Here is the applicationhost.config security section of the Template:

enter image description here

However, here is the same file in the new project created based off the template:

enter image description here

Notice that the section is missing entirely from the new project. So, now the question becomes how do you get this to copy over to new projects?

1 Answers

Answers 1

have you had a look at the global routes? it could be something routes not created or corrupted?

Read More

Tuesday, April 12, 2016

JQuery UI Autocomplete widget not working on a bootstrap modal

Leave a Comment

I have a bootstrap modal dialog on which I have a textbox that I want to leverage the functionality of jQuery UI Autocomplete widget. However the autocomplete widget isn't being fired at all. I know this as I placed a breakpoint on the action on my controller that should return the Json to be rendered by the autocomplete textbox. The action is never hit

Out of curiosity that I was doing something wrong, I copy pasted the textbox onto a View and to my dismay, the breakpoint on my action in the controller is hit. I have narrowed this down to the fact that may be the textbox is never wired to use the autocomplete feature once the DOM has loaded. Here is the textbox on my modal

 <input type="text" name="someName" id="autocomplete" data-autocomplete-url="@Url.Action("Autocomplete", "warehouses")" /> 

Here is the action method that returns the Json

public ActionResult Autocomplete(string term)     {         string[] names = { "Auma", "Dennis", "Derrick", "Dylan", "Mary", "Martha", "Marie", "Milly", "Abel", "Maria", "Bergkamp", "Arsene", "Alex", "Mwaura", "Achieng" };         var filtered = names.Where(a => a.IndexOf(term, StringComparison.OrdinalIgnoreCase) >= 0);         return Json(filtered, JsonRequestBehavior.AllowGet);     } 

And here is how I wire up the textbox to use the autocomplete widget

$(document).ready(function () { $('#autocomplete').autocomplete({     source: $(this).data('autocomplete-url'),     data: {term: $(this).val() } }); 

});

I have seen similar questions asked but none of them was due to the action not being hit.

1 Answers

Answers 1

As per the documentation for Bootstrap 3, they expose a set of events that you can hook into with most of their JS features.

In this case the events are: show, shown, hide, hidden and loaded

The following code will initialize your autocomplete input field after the modal has been shown. (replace myModal with the id of the modal you are going to show)

$(document).ready(function () {   $('#myModal').on('shown.bs.modal', function (e) {      $("#autocomplete').autocomplete('destroy'); //remove autocompete to reattach     $('#autocomplete').autocomplete({       source: $(this).data('autocomplete-url'),       data: {term: $(this).val() }     });    }); }); 

If you are fetching a partial that contains the input field and appending it to the modal during the toggle, it will be better to do this initialization in the callback from that ajax request.

Read More