Newboy Libor Kozak hit his first Villa goal as manager Paul Lambert enjoyed a third success in less than 12 months at the home of his former club.
The Czech Republic international fired home a 29th-minute winner, barely 60 seconds after replacing the injured Christrian Benteke.
Villa, who beat the Canaries in the Capital One Cup quarter-final last December and then won 2-1 at Carrow Road in May, were delighted to keep a clean sheet for the first time in 27 Barclays Premier League matches.
That was down to some resolute defending and two crucial Brad Guzan saves.
The American keeper kept out a sixth-minute penalty from Robert Snodgrass and brilliantly turned over a close-range Gary Hooper effort near the end.
Villa were twice close to scoring inside the opening five minutes.
With less than 60 seconds on the clock, Gabby Agbonlahor setting up Andi Weimann for a low drive which John Ruddy did well to hold.
The Villa strikers combined superbly again when Weimann sent Agbonlahor clear down the left and then made an intelligent run to receive the return pass just inside the penalty area.
The Austrian curled a fine low right-footer past Ruddy, only to see the ball come back off the inside of the far post. Benteke's shot from the rebound was saved by Ruddy, although it wouldn't have counted anyway, a linesman's flag indicating that the Belgian marksman was offside.
Having made such a positive start, though, the visitors could well have been behind in the sixth minute when Ciaran Clark handled after Snodgrass had headed down Nathan Redmond's deep cross.
Snodgrass struck the spot kick well but Guzan guessed correctly, leaping to his left to claw the ball away.
There was another let-off when Ricky van Wolfswinkel chested the ball just over from close range following a dangerous move, but Villa were menacing on the counter attack,
Benteke having a low shot deflected just wide before skipper Ron Vlaar sent a left-foot effort narrowly wide after Benteke had headed down Leandro Bacuna's right-wing corner.
Benteke's involvement in the game ended when he went down with what appeared to be a groin problem in the 25th minute.
Having received treatment, he collapsed as he attempted to rejoin the action, a misfortune which took place against the backdrop of van Wolfswinkel firing just wide for the Canaries.
But within a minute of Benteke's departure, his replacement had broken the deadlock.
Kozak might have done better with his first attempt, shooting straight at Ruddy after Weimann's astute pass had found him unmarked 12 yards out.
But when Agbonlahor collected the rebound and cut the ball back from the byeline, the Czech Republic international calmly side-footed into the corner of the net as Sebastien Bassong made a desperate challenge.
In Villa's next attack, Kozak's header was deflected for a corner following a Bacuna free-kick, although Weimann and Aleksanader Tonev were both well off target early in the second half as neat build-ups came to nothing.
Just before the hour mark, Guzan reacted well to tip the ball away after a Snodgrass cross diverted towards goal off Bacuna, although Nicklas Helenius, on as 61st-minute sub for Agbonlahor, almost doubled Villa's lead with a 22-yard free-kick which deflected just over the bar.
After Clark had ventured forward to head wide from a Bacuna flag kick, Tonev tested Ruddy with a long-range drive which was confidently held by the Norwich keeper.
Kozak then played a neat one-two with Fabian Delph before his angled shot went into the side netting off Ryan Bennett's boot.
Villa had certainly created enough chances to increase their advantage but 10 minutes from the end there were a couple of let-offs when Russell Martin's cross diverted just over off Clark and van Wolfswinkel's shot struck Antonio Luna and went out for another corner.
And in the 89th minute Guzan made an amazing save, somehow managing to stretch and tip the ball over from Gary Hooper's close-range effort following Javier Garrido's cross from the left.
Norwich City: Ruddy; Martin, Bassong (Bennett 38), Turner, Garrido; Snodgrass, Howson, Fer, Redmond (Pilkington 63); Elmander (Hooper 63), van Wolfswinkel. Unused subs: Bunn, Whittaker, Hoolahan, Tetley.
Villa: Guzan; Bacuna, Vlaar, Clark, Luna; Tonev, El Ahmadi, Delph; Weimann, Benteke (Kozak 28), Agbonlahor (Helenius 61). Unused subs: Steer, Baker, Bennett, Albrighton.