I am creating a new module in Magento (simple CRUD Application) , and the phtml file is called multiple times (twice) . Following is my code in layout xml file
<?xml version="1.0"?>
<layout version="0.1.0">
<businesshours_index_index>
<reference name="content">
<block type="businesshours/businesshours" name="businesshours" template="businesshours/businesshours.phtml" />
</reference>
</businesshours_index_index>
</layout>
This all are the method in my block class :-
<?php
class Techmentation_Businesshours_Block_Businesshours extends Mage_Core_Block_Template
{
public function __construct()
{
parent::__construct();
$branches = Mage::getModel('businesshours/businesshours')->getCollection();
$this->setCollection($branches);
}
public function getPostActionUrl()
{
return $this->helper('businesshours')->getBusinesshoursPostUrl();
}
public function _prepareLayout()
{
return parent::_prepareLayout();
}
public function getBusinesshours()
{
if (!$this->hasData('businesshours')) {
$this->setData('businesshours', Mage::registry('businesshours'));
}
return $this->getData('businesshours');
}
}
Why the content of phtml file is repeated twice ? How can I fix the issue ?
Related
Executed:
composer require uploadcare/uploadcare-php
I can find the library in vendor/uploadcare.
Then added to config/app.php:
'providers' => [
App\Providers\UploadcareServiceProvider::class,
]
and
'aliases' => Facade::defaultAliases()->merge([
'Uploadcare' => App\Facades\Uploadcare::class,
])->toArray(),
Then in App/Facades folder, created this file:
<?php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Uploadcare extends Facade {
protected static function getFacadeAccessor(){
return 'uploadcare';
}
}
This file is successfully referenced in config/app.php according to Visual Studio code.
Then in App/Providers I created UploadcareServiceProvider.php file:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Uploadcare\UploadcareConfiguration;
use Uploadcare\Interfaces\ConfigurationInterface;
class UploadcareServiceProvider extends ServiceProvider
{
public function boot()
{
$this->mergeConfigFrom(__DIR__.'/../../config/uploadcare.php', 'uploadcare');
}
public function register()
{
$this->app->bind(ConfigurationInterface::class, function ($app) {
return new UploadcareConfiguration();
});
$this->app->bind(Uploadcare\Api::class, function ($app) {
$config = $app->make(ConfigurationInterface::class);
return new Uploadcare\Api($config);
});
}
}
This file is successfully referenced in config/app.php according to Visual Studio code, it loads config/uploadcare.php which I have with the following (I redacted my public and private key):
<?php
return [
'public_key' => env('my-public-key'),
'private_key' => env('my-private-key'),
];
Then I created a controller to see whether I can successfully load a list of files form Uploadcare:
<?php
namespace App\Http\Controllers;
use Uploadcare\Api;
use App\Facades\Uploadcare;
use App\Uploadcare\UploadcareConfiguration;
use Uploadcare\Interfaces\ConfigurationInterface;
class UploadcareController extends Controller
{
public function index()
{
$api = Uploadcare::Api(config('uploadcare.public_key'), config('uploadcare.public_secret'));
$files = $api->files()->all();
return $files;
}
}
I call the controller using this route:
Route::get('/uploadcare', [UploadcareController::class, 'index']);
When visiting example.com/uploadcare I get the following error:
Target class [uploadcare] does not exist.
When I change the code in the controller to the following, I get the same error:
$files = Uploadcare::File()->getFileList();
When I hover Uploadcare in Visual Studio it successfully references the Facade.
I'm working on an inherited ASP.NET MVC 4 project using .net framework 4.5.
We've added a new configuration section files and relevant class files and from what we can tell (docs.Microsoft and other online guides) it's set up correctly.
The Problem
ConfigurationManager.GetSection() returns null.
According to the docs this returns null if the section doesn't exist. Troubleshooting this has been troublesome.
The Code
The website is an ASP.NET Web Application. Properties window sets assembly name to Client.Project.UI.Base (which is the DLL in the published bin). This is the assembly name used for the config types FQN and assembly in web.config.
NB: the config section SupportCaseConfiguration was originally in a separate file and the SupportTickets section just specified the configSource. This has been moved into the web.config to reduce the number of potential issues while troubleshooting.
web.config:
<configSections>
<!-- define type for new section -->
<section name="SupportTickets" type="Client.Project.UI.Base.Infrastructure.Services.SupportCaseConfigurationSection, Client.Project.UI.Base"/>
</configSections>
<!-- new config section -->
<SupportTickets>
<SupportCaseConfiguration>
<caseTypes>
<add name="tenant.TestCase" label="Test Case" recipient="email_here" ccList="" bccList="" />
</caseTypes>
</SupportCaseConfiguration>
</SupportTickets>
SupportCaseConfiguration.cs:
namespace Client.Project.UI.Base.Infrastructure.Services
{
using System.Configuration;
//Extend the ConfigurationSection class.
public class SupportCaseConfigurationSection : ConfigurationSection
{
[ConfigurationProperty("caseTypes", IsDefaultCollection = true)]
public CaseTypeElementCollection CaseTypes
{
get { return (CaseTypeElementCollection)this["caseTypes"]; }
}
}
//Extend the ConfigurationElementCollection class.
[ConfigurationCollection(typeof(CaseTypeElement))]
public class CaseTypeElementCollection : ConfigurationElementCollection
{
public CaseTypeElement this[int index]
{
get { return (CaseTypeElement)BaseGet(index); }
set
{
if (BaseGet(index) != null)
BaseRemoveAt(index);
BaseAdd(index, value);
}
}
protected override ConfigurationElement CreateNewElement()
{
return new CaseTypeElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((CaseTypeElement)element).Name;
}
}
//Extend the ConfigurationElement class. This class represents a single element in the collection.
public class CaseTypeElement : ConfigurationElement
{
[ConfigurationProperty("name", IsRequired = true)]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
[ConfigurationProperty("label", IsRequired = true)]
public string Label
{
get { return (string)this["label"]; }
set { this["label"] = value; }
}
[ConfigurationProperty("recipient", IsRequired = true)]
public string Recipient
{
get { return (string)this["recipient"]; }
set { this["recipient"] = value; }
}
[ConfigurationProperty("ccList", IsRequired = true)]
public string CcList
{
get { return (string)this["ccList"]; }
set { this["ccList"] = value; }
}
[ConfigurationProperty("bccList", IsRequired = true)]
public string BccList
{
get { return (string)this["bccList"]; }
set { this["bccList"] = value; }
}
}
}
Elsewhere, getting new config data:
SupportCaseConfigurationSection supportTicketsConfigurationSection = ConfigurationManager.GetSection("SupportCaseConfiguration") as SupportCaseConfigurationSection;
The site is being published locally, I can attach a debugger to ensure the latest versions of files are being used. I can see the config section in the published web.config.
I've been looking at this I can no longer see if anything is amiss. It all looks fine for me...
Any ideas, troubleshooting tips or even pointing out I'm being a muppet would be useful.
Cheers.
I can only assume the issue was something to do with the config classes in the site assembly.
Even after trying online examples, copypasting into the project, not even they worked.
As soon as I put the configuration section/element classes in a separate project (moved out of the website project) it started working.
I'm new to web programming and decided to switch from .net 4.5 to .net core.
My project has a static xml document in the following location:
wwwroot/Countries/en-GB.xml
How would one go about reading the xml file at the specified path? Eventually I will convert the data to a SelectList.
In .net 4.5 I used DataSet's and HttpConext...MapPath to read the xml document which no longer works in core mvc.
Any advice is greatly welcome.
First of all don't put your data source into wwwroot folder, because it is served publicly. Take a look at official docs:
The web root of your app is the directory in your project for public,
static resources like css, js, and image files. The static files
middleware will only serve files from the web root directory (and
sub-directories) by default.
So move Countries folder in your project's root folder.
To read xml data, you can use XmlSerializer. I will try to show how to read xml file:
First i assume you have xml content like below:
<?xml version="1.0" encoding="UTF-8" ?>
<Container>
<Countries>
<Country>
<Code>Code1</Code>
<Title>Title1</Title>
</Country>
<Country>
<Code>Code2</Code>
<Title>Title2</Title>
</Country>
</Countries>
</Container>
First describe types
public class Country
{
public string Code { get; set; }
public string Title { get; set; }
}
public class Container
{
public Country[] Countries { get; set; }
}
After that create a service for xml deserialization:
public interface ICountryService
{
Country[] GetCountries();
}
public class CountryService : ICountryService
{
private readonly IHostingEnvironment _env;
public CountryService(IHostingEnvironment env)
{
_env = env;
}
public Country[] GetCountries()
{
XmlSerializer ser = new XmlSerializer(typeof(Container));
FileStream myFileStream = new FileStream(_env.ContentRootPath + "\\Countries\\en-GB.xml", FileMode.Open);
return ((Container)ser.Deserialize(myFileStream)).Countries;
}
}
Then register service in ConfigureServices method:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddSingleton<ICountryService, CountryService>();
}
Finally inject and use it anywhere(such as in a controller)
public class SomeController : Controller
{
public SomeController(ICountryService countryService)
{
// use it
}
}
I have ASP.NET MVC4 project with custom AuthorizeAttribute to control the authorization. In order to explain my situation easier I created a dummy project to illustrate the issue.
I have one single controller
using System.Web.Mvc;
using MvcApplication2.Helper;
using MvcApplication2.Models;
namespace MvcApplication2.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new ViewModel();
return View(model);
}
[HttpPost]
public ActionResult Index(ViewModel model)
{
Session["ModelValue"] = model.InputValue;
return RedirectToAction("Step2");
}
[MyAuthorize]
public ActionResult Step2()
{
return View();
}
}
}
The purpose is very simple, From Index I accept some input, store the value in a session and redirect to Step2. I have my authorize attribute on step 2. The code for my attribute is
using System;
using System.Web;
using System.Web.Mvc;
namespace MvcApplication2.Helper
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext.Session["ModelValue"] == null)
{
return false;
}
else
{
string inputValue = httpContext.Session["ModelValue"] as string;
if (inputValue != "1")
{
return false;
}
else
{
return true;
}
}
}
}
}
The purpose is very simple, check if the session value is 1 or not.
Run the application, you input 1 in textbox and you see step2 view, if you input anything else you get the default 401.0 page.
Now I opened the web.config file to include
<system.web>
<customErrors mode="On" defaultRedirect="~/Error">
<error statusCode="401" redirect="~/401.htm" />
</customErrors>
<compilation debug="true" targetFramework="4.0" />
</system.web>
I hope when the application captures 401 code, I should see the content of 401.htm. But the reality is that I still get the default 401 error display from server.
Any idea why?
In addition use this:
<system.webServer>
<httpErrors>
<error statusCode="401" path="~/Home/Login"/>
<error statusCode="404" path="~/Error/NotFound"/>
</httpErrors>
</system.webServer>
How does one call a class static method from msbuild and store its results in a list?
EDIT: Okay, let me explain a bit further. I am using sandcastle help file builder to generate documentation for my application. One of the requirements is that you must specify the documentation sources as follows:
<DocumentationSources>
<DocumentationSource sourceFile="$(MSBuildProjectDirectory)\..\src\myApp\bin\Debug\myApp.exe" xmlns="" />
<DocumentationSource sourceFile="$(MSBuildProjectDirectory)\..\src\myApp\bin\Debug\myApp.xml" xmlns="" />
</DocumentationSources>
Sandcastle Help File Builder comes with a utils assembly that has a way of retrieving all dll and xml files from a specified directory. I want to call the method from this assembly and store its result as a list of <DocumentationSource>. This is a static method which returns Collection<string>
Custom Tasks are great but potential overkill if you want to do something simple. I believe Draco is asking about the Property Functions feature in MSBuild 4.
An example of setting a property by using a static function (ripped directly from above page):
<Today>$([System.DateTime]::Now)</Today>
And to call a static function on parameters:
$([Class]:: Property.Method(Parameters))
Or, perhaps you want something crazier like inline tasks.
Create a custom task calling that static method and returning an array of ITaskItem.
Or
You could try using the MSBuild Extension Pack Assembly.Invoke :
<PropertyGroup>
<StaticMethodAssemblyPath>path</StaticMethodAssemblyPath>
</PropertyGroup>
<MSBuild.ExtensionPack.Framework.Assembly TaskAction="Invoke"
NetArguments="#(ArgsM)"
NetClass="StaticMethodClassName"
NetMethod="StaticMethodName"
NetAssembly="${StaticMethodAssemblyPath}">
<Output TaskParameter="Result" PropertyName="R"/>
</MSBuild.ExtensionPack.Framework.Assembly>
Generally, the most flexible option is to create a custom MSBuild task. This is all untested code meant to just to give you the idea:
In your msbuild file:
<UsingTask TaskName="FindFiles" AssemblyFile="FindFiles.dll" />
<!--
As you'll see below, SearchDirectory and SearchPatterns are input parameters,
MatchingFiles is an output parameter, SourceFiles is an ItemGroup assigned to
the output.
-->
<FindFiles SearchDirectory="$(MyDirectory)" SearchPatterns="*.dll;*.xml">
<Output ItemName="SourceFiles" TaskParameter="MatchingFiles" />
</FindFiles>
<!-- You can then use the generated ItemGroup output elsewhere. -->
<DocumentationSources>
<DocumentationSource sourceFile="#(SourceFiles)" xmlns="" />
</DocumentationSources>
FindFiles.cs:
using System;
using System.IO;
using System.Collections.Generic;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace FindFiles
{
public class FindFiles : Task
{
// input parameter
[Required]
public string SearchDirectory { get; set; }
// output parameter
[Required]
public string[] SearchPatterns { get; set; }
[Output]
public string[] MatchingFiles { get; private set; }
private bool ValidateParameters()
{
if (String.IsNullOrEmpty(SearchDirectory))
{
return false;
}
if (!Directory.Exists(SearchDirectory))
{
return false;
}
if (SearchPatterns == null || SearchPatterns.Length == 0)
{
return false;
}
return true;
}
// MSBuild tasks use the command pattern, this is where the magic happens,
// refactor as needed
public override bool Execute()
{
if (!ValidateParameters())
{
return false;
}
List<string> matchingFiles = new List<string>();
try
{
foreach (string searchPattern in SearchPatterns)
{
matchingFiles.AddRange(
Directory.GetFiles(SearchDirectory, searchPattern)
);
}
}
catch (IOException)
{
// it might be smarter to just let this exception fly, depending on
// how you want the task to behave
return false;
}
MatchingFiles = matchingFiles.ToArray();
return true;
}
}
}